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 |