@luxonis/depthai-pipeline-lib 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,16 +6,20 @@ import { css } from '../styled-system/css/css.mjs';
6
6
  import { DOCS_BASE_URL, NodesWithLinks, } from '../services/pipeline.js';
7
7
  const NodeHandles = props => {
8
8
  const { handles, type } = props;
9
- return (_jsx(Flex, { full: true, direction: "column", align: type === 'input' ? 'start' : 'end', children: handles.map(({ type: handleType, id, blocking, queueSize, name }) => (_jsxs(Flex, { position: "relative", align: "end", direction: handleType === 'input' ? 'row' : 'row-reverse', children: [_jsx(Handle, { type: handleType === 'input' ? 'target' : 'source', position: handleType === 'input' ? Position.Left : Position.Right, id: name, isConnectable: false, className: css({
9
+ return (_jsx(Flex, { full: true, direction: "column", align: type === 'input' ? 'start' : 'end', children: handles.map(({ type: handleType, id, blocking, queueSize, name, maxQueueSize, fps }) => (_jsxs(Flex, { position: "relative", align: "end", direction: handleType === 'input' ? 'row' : 'row-reverse', children: [_jsx(Handle, { type: handleType === 'input' ? 'target' : 'source', position: handleType === 'input' ? Position.Left : Position.Right, id: name, isConnectable: false, className: css({
10
10
  width: 'custom.handle.dot!',
11
11
  height: 'custom.handle.dot!',
12
12
  backgroundColor: blocking ? 'dark.warning!' : 'dark.success!',
13
13
  border: 'none!',
14
- }) }), _jsx(SubLabel, { className: css({
15
- ...(type === 'input' //
16
- ? { marginLeft: 'xs' }
17
- : { marginRight: 'xs' }),
18
- }), text: type === 'input' ? `[${queueSize}] ${name}` : name, break: "none" })] }, id))) }));
14
+ }) }), _jsx(NodeHandlesSubLabel, { type: type, name: name, queueSize: queueSize, maxQueueSize: maxQueueSize, fps: fps })] }, id))) }));
15
+ };
16
+ const NodeHandlesSubLabel = props => {
17
+ const { type, name, queueSize, maxQueueSize, fps } = props;
18
+ return (_jsx(SubLabel, { className: css({
19
+ ...(type === 'input' //
20
+ ? { marginLeft: 'xs' }
21
+ : { marginRight: 'xs' }),
22
+ }), text: `[${fps ? `${fps.toFixed(1)} | ` : ''}${maxQueueSize ? `${maxQueueSize}/${queueSize}` : queueSize}] ${name}`, break: "none" }));
19
23
  };
20
24
  export const PipelineNode = props => {
21
25
  const { data: node } = props;
@@ -1,7 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { FlexProps } from '@luxonis/common-fe-components';
3
- import type { Pipeline } from '../services/pipeline.js';
3
+ import type { ParsedNode, Pipeline } from '../services/pipeline.js';
4
+ import type { PipelineState } from '../services/pipeline-state.js';
4
5
  export type PipelineCanvasProps = FlexProps & {
5
6
  pipeline: Pipeline | null;
7
+ pipelineState?: PipelineState[] | null;
6
8
  };
9
+ export declare const updateNodesOnPipelineStateChange: (nodes: ParsedNode[], pipelineState: PipelineState[]) => ParsedNode[];
7
10
  export declare const PipelineCanvas: React.FC<PipelineCanvasProps>;
@@ -86,7 +86,49 @@ const adjustNodes = (nodes) => {
86
86
  });
87
87
  return [...positionedGroups, ...positionedNodes];
88
88
  };
89
- const PipelineCanvasBody = ({ pipeline, ...flexProps }) => {
89
+ export const updateNodesOnPipelineStateChange = (nodes, pipelineState) => {
90
+ const parsedNodes = [];
91
+ for (const node of nodes) {
92
+ const nodeState = pipelineState.find(state => state.id.toString() === node.id.toString());
93
+ const inputHandles = node.data.handles.input;
94
+ const outputHandles = node.data.handles.output;
95
+ const newInputHandles = [];
96
+ for (const inputHandle of inputHandles) {
97
+ const obj = { ...inputHandle };
98
+ const inputState = nodeState?.inputs[inputHandle.name];
99
+ if (inputState) {
100
+ obj.maxQueueSize = inputState.numQueued;
101
+ obj.fps = inputState.timing.fps;
102
+ }
103
+ newInputHandles.push(obj);
104
+ }
105
+ const newOutputHandles = [];
106
+ for (const outputHandle of outputHandles) {
107
+ const obj = { ...outputHandle };
108
+ const outputState = nodeState?.outputs[outputHandle.name];
109
+ if (outputState) {
110
+ obj.maxQueueSize = outputState.numQueued;
111
+ obj.fps = outputState.timing.fps;
112
+ }
113
+ newOutputHandles.push(obj);
114
+ }
115
+ parsedNodes.push({
116
+ ...node,
117
+ data: {
118
+ ...node.data,
119
+ handles: {
120
+ input: newInputHandles,
121
+ output: newOutputHandles,
122
+ },
123
+ },
124
+ });
125
+ }
126
+ return parsedNodes;
127
+ };
128
+ const PipelineCanvasBody = ({ pipeline,
129
+ // eslint-disable-next-line no-warning-comments
130
+ // TODO: Remove optional after pipelineState is implemented in Viewer and Visualizer
131
+ pipelineState = null, ...flexProps }) => {
90
132
  const { fitView, setViewport, getViewport } = useReactFlow();
91
133
  const autoArrangeRef = React.useRef(true);
92
134
  const widthSelector = (state) => state.width;
@@ -95,6 +137,8 @@ const PipelineCanvasBody = ({ pipeline, ...flexProps }) => {
95
137
  const reactFlowHeight = useStore(heightSelector);
96
138
  const nodesInitialized = useNodesInitialized();
97
139
  const [isAutoLayoutingFinished, setIsAutoLayoutingFinished] = React.useState(false);
140
+ const [isNodesUpdatedWithState, setIsNodesUpdatedWithState] = React.useState(false);
141
+ const [shouldFitAndResize, setShouldFitAndResize] = React.useState(false);
98
142
  React.useEffect(() => {
99
143
  void fitView();
100
144
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -114,9 +158,19 @@ const PipelineCanvasBody = ({ pipeline, ...flexProps }) => {
114
158
  const adjustedNodes = adjustNodes(nodes);
115
159
  setNodes([...adjustedNodes]);
116
160
  setIsAutoLayoutingFinished(true);
161
+ setShouldFitAndResize(true);
117
162
  }
118
163
  // eslint-disable-next-line react-hooks/exhaustive-deps
119
164
  }, [nodesInitialized, isAutoLayoutingFinished]);
165
+ React.useEffect(() => {
166
+ if (pipelineState && nodes.length > 0 && !isNodesUpdatedWithState) {
167
+ const updatedNodes = updateNodesOnPipelineStateChange(nodes, pipelineState);
168
+ setNodes([...updatedNodes]);
169
+ setIsNodesUpdatedWithState(true);
170
+ setShouldFitAndResize(true);
171
+ }
172
+ // eslint-disable-next-line react-hooks/exhaustive-deps
173
+ }, [pipelineState, nodes, isNodesUpdatedWithState]);
120
174
  const setViewportAndFit = async (x, y, zoom, nds) => {
121
175
  await setViewport({ x, y, zoom });
122
176
  await fitView({ nodes: nds });
@@ -131,6 +185,14 @@ const PipelineCanvasBody = ({ pipeline, ...flexProps }) => {
131
185
  }
132
186
  // eslint-disable-next-line react-hooks/exhaustive-deps
133
187
  }, [nodes, edges]);
188
+ React.useEffect(() => {
189
+ if (shouldFitAndResize) {
190
+ const viewport = getViewport();
191
+ void setViewportAndFit(viewport.x, viewport.y, viewport.zoom, nodes);
192
+ setShouldFitAndResize(false);
193
+ }
194
+ // eslint-disable-next-line react-hooks/exhaustive-deps
195
+ }, [shouldFitAndResize]);
134
196
  return (_jsxs(Flex, { align: "center", justify: "center", full: true, height: "container.xs", rounded: "common", border: "base", ...flexProps, children: [!pipeline && _jsx(Header, { text: "Loading pipeline..." }), pipeline && (_jsx(ReactFlow, { nodes: nodes, edges: edges, onNodeDragStart: () => (autoArrangeRef.current = false), onNodesChange: onNodesChange, fitView: true, nodeTypes: { generic: PipelineNode }, minZoom: 0.4 }))] }));
135
197
  };
136
198
  export const PipelineCanvas = props => (_jsx(ReactFlowProvider, { children: _jsx(PipelineCanvasBody, { ...props }) }));
@@ -1,4 +1,6 @@
1
1
  export { parsePipeline } from './services/pipeline.js';
2
2
  export type { Pipeline, RawPipelinePayload } from './services/pipeline.js';
3
+ export { parsePipelineState } from './services/pipeline-state.js';
4
+ export type { PipelineState, RawPipelineStatePayload } from './services/pipeline-state.js';
3
5
  export { PipelineCanvas } from './components/PipelineCanvas.js';
4
6
  export type { PipelineCanvasProps } from './components/PipelineCanvas.js';
package/dist/src/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { parsePipeline } from './services/pipeline.js';
2
+ export { parsePipelineState } from './services/pipeline-state.js';
2
3
  export { PipelineCanvas } from './components/PipelineCanvas.js';
@@ -0,0 +1,42 @@
1
+ export type RawPipelineStatePayload = {
2
+ nodeStates: RawPipelineState[];
3
+ };
4
+ export type IOStates = {
5
+ [key: string]: {
6
+ numQueued: number;
7
+ timing: TimingWithFps;
8
+ };
9
+ };
10
+ type Timing = {
11
+ averageMicrosRecent: number;
12
+ maxMicros: number;
13
+ maxMicrosRecent: number;
14
+ medianMicrosRecent: number;
15
+ minMicros: number;
16
+ minMicrosRecent: number;
17
+ stdDevMicrosRecent: number;
18
+ };
19
+ type TimingWithFps = {
20
+ durationStats: Timing;
21
+ fps: number;
22
+ };
23
+ export type RawPipelineState = [
24
+ number,
25
+ {
26
+ events: any[];
27
+ inputStates: IOStates;
28
+ inputsGetTiming: TimingWithFps;
29
+ mainLoopTiming: TimingWithFps;
30
+ otherTimings: object;
31
+ outputStates: IOStates;
32
+ outputsSendTiming: TimingWithFps;
33
+ state: number;
34
+ }
35
+ ];
36
+ export type PipelineState = {
37
+ id: number;
38
+ inputs: IOStates;
39
+ outputs: IOStates;
40
+ };
41
+ export declare function parsePipelineState(rawPayload: RawPipelineStatePayload): PipelineState[];
42
+ export {};
@@ -0,0 +1,13 @@
1
+ export function parsePipelineState(rawPayload) {
2
+ const { nodeStates } = rawPayload;
3
+ const parsedNodeStates = [];
4
+ for (const [nodeId, nodeState] of nodeStates) {
5
+ const currentNode = {
6
+ id: nodeId,
7
+ inputs: nodeState.inputStates,
8
+ outputs: nodeState.outputStates,
9
+ };
10
+ parsedNodeStates.push(currentNode);
11
+ }
12
+ return parsedNodeStates;
13
+ }
@@ -43,6 +43,8 @@ export type ParsedHandle = {
43
43
  type: 'input' | 'output';
44
44
  blocking: boolean;
45
45
  queueSize: number;
46
+ maxQueueSize?: number;
47
+ fps?: number;
46
48
  };
47
49
  export type ParsedNode = Node<{
48
50
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luxonis/depthai-pipeline-lib",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "main": "./dist/src/index.js",