Skip to main content
Version: 3.0
Beta

App Studio is in release 3.0 as Beta: a paid add-on that no edition includes by default. A licence or a trial licence that includes the app_studio feature switches it on. The module is on by default, so the licence decides. This reference may change while App Studio is in Beta; the SDK changelog records each change.

Generated

Generated from the SDK sources by scripts/appstudio-sdk-docs.cjs for runtime-v1. Do not edit; run npm run appstudio:docs:sdk.

@maestrohub/scene

Beta: look up the scene kit an app uses to draw its line in 3D, with stations, buffers, finished goods and operators following live topics.

Runtime
runtime-v1
Exports
47 (22 values, 25 types)

The App Studio scene kit: a live 3D production line drawn from a scene spec and bound to topics (Beta in 3.0).

Runtime: runtime-v1. 47 exports (22 values, 25 types). Import with:

import { ... } from '@maestrohub/scene';

Components​

Scene​

function Scene({ spec, values, onSelect, height, quality, view, focus, overlay, hud }: SceneProps): JSX.Element

Scene draws a production line from a scene spec and binds it to live topics: station state drives the stack light and motion, a rise in the good counter sends a part down the line, a rise in the reject counter drops one into the scrap bin, a buffer holds as many parts as its level. Needs uns:read for live topics (not for values).

Example

import scene from './scene.json';
<Scene spec={scene} onSelect={(id) => setSelected(id)} />

ValueStream​

function ValueStream({ spec, values, part }: ValueStreamProps): JSX.Element | null

ValueStream draws a scene's value stream as a flat VSM sheet, bound to its live topics (or to values). Renders nothing when the scene has no vsm.

Example

<ValueStream spec={scene} />

Functions​

bufferFill​

function bufferFill(raw: unknown, capacity: number): number

How many parts a buffer shows: the level clamped to 0..capacity.

counter​

function counter(raw: unknown): number | null

A counter value as a number (null when absent or not numeric).

durationText​

function durationText(raw: unknown): string

A duration in seconds as text: "0.32 s", "12 s", "41 min", "1.7 h"; "–" when absent.

isOffBelt​

function isOffBelt(kind: StationKind): boolean

True for process equipment, which stands off the belt.

levelOf​

function levelOf(raw: unknown, levelMax?: number): number | null

A tank's fill 0..1: a height against levelMax when given, else a share (0..1 or 0..100); null when absent.

mediumColor​

function mediumColor(id: string | undefined): string

A medium's colour (product's for an unknown or absent one).

percentText​

function percentText(raw: unknown): string

A share (0..1 or 0..100) as a whole percentage; "–" when absent.

pipeFlowing​

function pipeFlowing(spec: SceneSpec, p: PipeSpec, values: Record<string, unknown>): boolean

Whether a pipe flows: its flow topic above zero, or (no flow topic) its from-station running.

plainValue​

function plainValue(v: unknown): unknown

Reads a plain value out of a topic value: the value itself, or its value / state field.

positionOf​

function positionOf(raw: unknown): number | null

A valve's opening 0..1, from a share (0..1 or 0..100), a word (open, closed, moving) or a boolean; null when absent.

progress​

function progress(raw: unknown): number | null

Cycle progress as 0..1 (accepts 0..100), null when absent.

readoutAlert​

function readoutAlert(raw: unknown, r: ReadoutSpec): 0 | 1 | 2

0 fine, 1 past the warning, 2 at or past the alarm. Not a number is never an alert.

readoutText​

function readoutText(raw: unknown): string

A readout's value as text: whole numbers as they are, others to one decimal.

sceneTopics​

function sceneTopics(spec: SceneSpec): string[]

Every topic path a spec binds, once each.

stageRow​

function stageRow(key: "cycle" | "uptime" | "oee", bind: StageSpec["bind"], values: Record<string, unknown>): { text: string; title?: string; }

A stage box's row, as the flat sheet, the lead-time ladder and the overlay cards all show it: the cycle time as a duration, uptime and OEE as percentages. When the stage's scheduled topic is false every row reads "Not scheduled" (the reason as title): none of the three is published then, so what is left on their topics is the last scheduled window's. A missing scheduled topic or value is no data yet, not "not scheduled": the rows then read as they are. A scheduled stage whose oeeComputed topic is false reads "–" for OEE, with the reason: no OEE was published, so what is on its topic is an older window's.

stationState​

function stationState(raw: unknown, own?: Record<string, StationState>): StationState

stationState maps a raw state value to a kit state: the station's own map first, then the shared default map (upper-cased), booleans as running/off. Unknown values read as idle, never as running.

webglAvailable​

function webglAvailable(): boolean

True when this browser can draw WebGL at all.

worstTopics​

function worstTopics(v: VsmSpec | undefined): string[]

A value stream's worst-stage topics, one or many.

Constants​

SCENE_VOCABULARY​

const SCENE_VOCABULARY: { version: number; kinds: StationKind[]; states: StationState[]; defaultStates: Record<string, StationState>; qualities: SceneQuality[]; maxStations: number; maxBuffers: number; maxCapacity: number; idPattern: string; maxLabelOffset: number; maxAreas: number; maxLines: number; maxViews: number; maxCoordinate: number; facings: number[]; lineSpacing: { min: number; max: number; default: number; }; besideOffset: number; offBelt: StationKind[]; media: { id: Medium; color: string; }[]; products: Product[]; maxReadouts: number; maxUnit: number; maxStages: number; maxInventories: number; maxSystems: number; maxPipes: number; maxVia: number; rackHeight: number; pipeLevels: ("rack" | "floor")[]; }

The shared vocabulary (also read by the server).

Members

  • besideOffset: number
  • defaultStates: Record<string, StationState>
  • facings: number[]
  • idPattern: string
  • kinds: StationKind[]
  • lineSpacing: { min: number; max: number; default: number; }
  • maxAreas: number
  • maxBuffers: number
  • maxCapacity: number
  • maxCoordinate: number
  • maxInventories: number
  • maxLabelOffset: number
  • maxLines: number
  • maxPipes: number
  • maxReadouts: number
  • maxStages: number
  • maxStations: number
  • maxSystems: number
  • maxUnit: number
  • maxVia: number
  • maxViews: number
  • media: { id: Medium; color: string; }[]
  • offBelt: StationKind[]
  • pipeLevels: ("rack" | "floor")[]
  • products: Product[]
  • qualities: SceneQuality[]
  • rackHeight: number
  • states: StationState[]
  • version: number

STATE_COLOR​

const STATE_COLOR: Record<StationState, string>

The colour each state shows on the stack light and the station label.

Members

  • blocked: string
  • faulted: string
  • idle: string
  • maintenance: string
  • off: string
  • running: string
  • starved: string

Types​

AreaSpec​

interface AreaSpec

A hall or zone on the floor: painted, walled low, named. at is its centre.

Members

  • at: FloorPoint
  • id: string
  • label?: string | undefined
  • size: { w: number; d: number; }: Width along x and depth along z, in metres.

BufferSpec​

interface BufferSpec

A buffer conveyor on the line, filled by a level topic: after a station (after), or before one (before), which is how a raw material buffer sits ahead of the first station. Exactly one of the two.

Members

  • after?: string | undefined: The station this buffer follows.
  • before?: string | undefined: The station this buffer feeds: the buffer sits just upstream of it.
  • bind?: { level?: string; } | undefined
  • capacity: number: Parts the buffer holds when full.
  • id: string
  • label?: string | undefined
  • labelOffset?: LabelOffset | undefined: Moves the buffer's label.

FloorPoint​

interface FloorPoint

A place on the floor, in metres.

Members

  • x: number
  • z: number

InventorySpec​

interface InventorySpec

An inventory triangle at a station (a tank, a buffer's station): how much waits there, and for how long.

Members

  • at: string
  • bind?: { amount?: string; wait?: string; } | undefined
  • id: string
  • label?: string | undefined
  • unit?: string | undefined

LabelOffset​

interface LabelOffset

Moves a label from where the kit puts it, in metres along the line (x), up (y) and towards the viewer (z); each at most maxLabelOffset. For labels that crowd each other near the end of a long line.

Members

  • x?: number | undefined
  • y?: number | undefined
  • z?: number | undefined

LineSpec​

interface LineSpec

A line of stations. Its first belt station stands at at; the rest follow every spacing metres (default 7) in the facing direction: 0 runs along +x, 90 along -z, 180 along -x, 270 along +z.

Members

  • area?: string | undefined: The area it stands in (for grouping and the 2D view).
  • at: FloorPoint
  • facing?: 0 | 90 | 180 | 270 | undefined
  • id: string
  • label?: string | undefined
  • product?: Product | undefined: What rides the belt (default part).
  • spacing?: number | undefined

Medium​

type Medium = 'product' | 'syrup' | 'water' | 'steam' | 'air' | 'gas' | 'cip';

What fills a tank or a header, and the colour it shows.

ModelRef​

interface ModelRef

A .glb model stored as an attachment on an app record (it replaces the kit's body for the station).

Members

  • attachment: string: The attachment id of the .glb.
  • collection: string: The storage collection holding the record.
  • key: string: The record's key.
  • scale?: number | undefined: Uniform scale applied to the model (default 1).

OperatorSpec​

interface OperatorSpec

A person on the line. They stand at home; when a station they cover faults, they walk to it, work on it, and walk back once it recovers.

Members

  • covers?: string[] | undefined: Stations they answer (default: only home).
  • home: string: The station they stand at when nothing needs them.
  • id: string
  • label?: string | undefined
  • labelOffset?: LabelOffset | undefined: Moves the operator's name tag.
  • vest?: string | undefined: Vest colour (default hi-vis orange).

OutputSpec​

interface OutputSpec

Where finished parts pile up: pallets after a station, filled in layers.

Members

  • after: string: The station that puts parts here (often the last one, an unload robot).
  • bind?: { count?: string; } | undefined
  • id: string
  • label?: string | undefined
  • labelOffset?: LabelOffset | undefined: Moves the output's label (the count above its pallet).
  • perPallet?: number | undefined: Parts on one full pallet (default 24); a full pallet moves to the shipped stack.

PipeSpec​

interface PipeSpec

A pipe between two stations, in its medium's colour, moving while it flows. It runs on the overhead rack between lines (each medium at its own height) and along the floor within a line; level overrides that, via steers it through floor points.

Members

  • bind?: { flow?: string; } | undefined: Flow through it: beads move while it is above zero. Without it, the pipe flows while its from-station runs.
  • from: string
  • id: string
  • label?: string | undefined
  • level?: "rack" | "floor" | undefined
  • medium: Medium
  • to: string
  • via?: FloorPoint[] | undefined

Product​

type Product = 'part' | 'bottle' | 'can' | 'case';

What rides a line's belt.

ReadoutSpec​

interface ReadoutSpec

A value a station shows on its screen, its label and its panel. Past warn it needs attention (amber), at or past alarm it is in alarm (red: the stack light turns red, a pump shakes, operators come). The limits apply on the when side: above (the default) or below.

Members

  • alarm?: number | undefined
  • label: string
  • topic: string
  • unit?: string | undefined
  • warn?: number | undefined
  • when?: "above" | "below" | undefined

SceneHud​

interface SceneHud

The slots of Scene's hud: each is any React content.

Members

  • bottom?: ReactNode: Along the bottom, between the corners (filling the page, the value stream's ladder goes here).
  • bottomLeft?: ReactNode
  • bottomRight?: ReactNode
  • topLeft?: ReactNode
  • topRight?: ReactNode

SceneProps​

interface SceneProps

Props for Scene.

Members

  • focus?: string | undefined: A station's id: the camera flies in on it (unset: back to the view).
  • height?: number | "fill" | undefined: Height in pixels (default 460), or "fill": the height the parent gives it, for a canvas that fills the page (give the parent a height, e.g. height: '100vh' or a flex child). The width follows the container.
  • hud?: SceneHud | undefined: An app's own panels, floating over the picture: in its corners and along its bottom. The layer between them lets clicks through to the scene. Without WebGL they stand above the cards instead.
  • onSelect?: ((stationId: string) => void) | undefined: A station was clicked (its id).
  • overlay?: "vsm" | undefined: "vsm" shows the value stream over the plant (stage boxes, inventory triangles, systems) with its ladder underneath.
  • quality?: SceneQuality | undefined: Overrides the spec's quality.
  • spec: SceneSpec: The scene: usually import scene from './scene.json'.
  • values?: Record<string, unknown> | undefined: Topic path → value, instead of live topics: sample data, a replay, or values the app computed. When set, the scene subscribes to nothing.
  • view?: string | undefined: A view's id from spec.views: the camera flies there (unset: the whole scene).

SceneQuality​

type SceneQuality = 'low' | 'balanced' | 'high';

Rendering quality: balanced is the default for shop-floor screens.

SceneSpec​

interface SceneSpec

The whole scene: what src/scene.json holds.

Members

  • areas?: AreaSpec[] | undefined: Halls and zones on the floor (a plant).
  • buffers?: BufferSpec[] | undefined
  • lines?: LineSpec[] | undefined: Lines of stations; without them the scene is one straight line.
  • operators?: OperatorSpec[] | undefined
  • outputs?: OutputSpec[] | undefined
  • pipes?: PipeSpec[] | undefined: Pipes between stations.
  • quality?: SceneQuality | undefined
  • stations: StationSpec[]
  • version: 1
  • views?: ViewSpec[] | undefined: Named camera views; <Scene view> flies to one.
  • vsm?: VsmSpec | undefined: The value stream layer.

StageSpec​

interface StageSpec

A process box: some stations, with their cycle time, uptime and OEE.

Members

  • bind?: { cycle?: string; uptime?: string; oee?: string; scheduled?: string; oeeComputed?: string; } | undefined: scheduled: a topic whose value is false when the stage had no planned production in the window. Its uptime and OEE then read "Not scheduled" (availability is undefined without planned time), not a blank or the last share still on their topics. oeeComputed: a topic whose value is false when the stage was scheduled but its OEE could not be computed in the window (too few counter readings). OEE then reads "–" with the reason, not the last OEE still on its topic. Not scheduled wins over not computed.
  • id: string
  • label?: string | undefined
  • stations: string[]

StationKind​

type StationKind = 'cnc' | 'washer' | 'tester' | 'robot' | 'generic' | 'filler' | 'capper' | 'labeller' | 'palletizer' | 'tank' | 'pump' | 'valve' | 'boiler' | 'compressor' | 'header' | 'instrument' | 'heat_exchanger';

The kinds of station the kit can draw.

StationSpec​

interface StationSpec

One station on the line, drawn in spec order from left to right.

Members

  • beside?: string | undefined: Stands next to this station of the same line, off the belt: a standby pump beside its duty pump. Takes no place in the line's order.
  • bind?: { state?: string; good?: string; bad?: string; cycle?: string; level?: string; flow?: string; position?: string; speed?: string; } | undefined: Topic paths the station reads.
  • id: string: Unique within the scene; also the key onSelect reports.
  • kind: StationKind
  • label?: string | undefined: Shown above the station; defaults to the id.
  • labelOffset?: LabelOffset | undefined: Moves the station's label.
  • levelMax?: number | undefined: A tank's level reading when full, when the level is not a share: 3.0 for a 3 m tank read in metres.
  • line?: string | undefined: The line it stands on (a scene with lines; every station then names one).
  • medium?: Medium | undefined: What fills a tank or a header (default product).
  • model?: ModelRef | undefined: A stored .glb drawn instead of the kit body.
  • readouts?: ReadoutSpec[] | undefined: Up to four values it shows, with limits.
  • states?: Record<string, StationState> | undefined: Raw state value → kit state, for values the default map does not know.

StationState​

type StationState = 'running' | 'idle' | 'starved' | 'blocked' | 'faulted' | 'maintenance' | 'off';

The states a station shows (stack light, motion, label).

SystemSpec​

interface SystemSpec

An information system (ERP, MES, CMMS) and the lines or areas it talks to.

Members

  • bind?: { value?: string; } | undefined
  • id: string
  • label?: string | undefined
  • to?: string[] | undefined

ValueStreamProps​

interface ValueStreamProps

Props for ValueStream.

Members

  • part?: "all" | "ladder" | undefined: "ladder" draws only the lead-time ladder (what <Scene overlay="vsm"> puts under the plant).
  • spec: SceneSpec: The scene; only its vsm is drawn.
  • values?: Record<string, unknown> | undefined: Topic path → value instead of live topics (then nothing is subscribed).

ViewSpec​

interface ViewSpec

A named camera view: an area, a line, some stations, or (none) the whole scene.

Members

  • area?: string | undefined
  • id: string
  • label?: string | undefined
  • line?: string | undefined
  • stations?: string[] | undefined

VsmSpec​

interface VsmSpec

The value stream layer. Every number is a topic a pipeline publishes (cycle time and waits in seconds, shares as 0..1 or 0..100); the kit only shows them, over the plant (<Scene overlay="vsm">) and as a flat sheet (<ValueStream>).

Members

  • inventories?: InventorySpec[] | undefined
  • ladder?: { steps: string[]; bind?: { lead?: string; valueAdded?: string; }; } | undefined: The lead-time ladder: stage and inventory ids in the order the product meets them.
  • stages?: StageSpec[] | undefined
  • systems?: SystemSpec[] | undefined
  • worst?: string | string[] | undefined: A topic (or one per line) whose value is the id of the stage losing most now: it carries the kaizen burst.