@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.
- package/dist/src/components/Node.js +10 -6
- package/dist/src/components/PipelineCanvas.d.ts +4 -1
- package/dist/src/components/PipelineCanvas.js +63 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +1 -0
- package/dist/src/services/pipeline-state.d.ts +42 -0
- package/dist/src/services/pipeline-state.js +13 -0
- package/dist/src/services/pipeline.d.ts +2 -0
- package/package.json +1 -1
|
@@ -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(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
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 }) }));
|
package/dist/src/index.d.ts
CHANGED
|
@@ -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
|
@@ -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
|
+
}
|