Skip to main content

Creating a Node

To create more complicated logic, sometimes it is necessary to create nodes with custom logic. You are able to do this by modifying std-nodes.js and std-nodes.json to add as many custom nodes as required.

std-nodes.json

The json file defines all the available nodes and their inputs and outputs. To add a new node we can create a new entry in the nodes object.

{
"nodes": {
...
"calculateMagnitude": {
"construct": "construct_calculateMagnitude",
"fi": {
"in": {
"entry": "calculate",
"args": [
"x",
"y"
]
}
},
"bi": {
"x": {
"kind": "float64",
"default": 0
},
"y": {
"kind": "float64",
"default": 0
}
},
"bo": {
"magnitude": {
"entry": "getMagnitude",
"kind": "float64",
"default": 0
}
},
"fo": {
"finished": {}
}
}
...
}
}

Each node must have a construct key, which tells flow which JS function to call to create a new node. We create this function in std_nodes.js.

The other toplevel keys are: fi, bi, fo and bo which stand for forwards/backwards input/output.

Forward inputs are the entrypoints to the node and call a function that operates on it's arguments.

Backwards inputs are the inputs to the node from other nodes, and backwards outputs are the outputs of the node that are connected to nodes further along in the flow. Backwards outputs must have an entry which defines how the output gets it's value.

Forward outputs signal events such as the node finishing and trigger the next node in the flow.

std-nodes.js

The javascript file defines the behaviour of the nodes.

...

// Define the Magnitude Node
export function MagnitudeNode() {
// Initialize any instance data for each node. There a couple of reasons to do this here. The first being that it ensures that all instance fields start at known values. Secondly, it ensures that any user that can access this node, can immediately see what data is persisted for each instance without having to read every line of code for the node. The second point is becomes more important as the size of a node increases.
this.mag = 0.0;

// 'calculate' entrypoint
this.calculate = function (ctx, x, y) {
// Save magnitude to instance
this.mag = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));

// Call next node in flow
$ld.lookupCallable(this, "$finished").call(ctx);
}

// 'getMagnitude' entrypoint
this.getMagnitude = function (ctx) {
// return the saved magnitude
return this.mag;
}
};

// Register the Magnitude node
export var constructMagnitudeNode = $RegisterClass(MagnitudeNode);

...

Input/Output Types

Name
bool
int8
int16
int32
int64
uint8
uint16
uint32
uint64
float32
float64
[]interface
[]string
map[string]interface
map[string]string
Duration
RocosURI
TelemetryMessage
[]TelemetryMessage
CommandResponse
[]CommandResponse
CallableResponse
[]CallableResponse
ControlAck
[]ControlAck
PayloadValue
JSONString
interface
Transform
Marker