Could you use environment variables in the individual machines, so the flows are the same on all devices?
I thought so, but I must be missing something.
Post here a sample flow which just posts a flow with a single node for us to look at.
I've been attempting to do this using curl with command line using the command (and variations thereof) that I posted before.
CYCLES=$(<Cycles.json)
curl -H "Authorization: Bearer ${TOKEN}" -X PUT http://${IP}:1880/flow/f72d85c5e090800f -d `"${CYCLES}"`
CYCLES=$(<Cycles.json)
curl -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -X PUT http://${IP}:1880/flow/f72d85c5e090800f -d `"${CYCLES}"`
curl -d "@Cycles.json" -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -X PUT http://${IP}:1880/flow/:f72d85c5e090800f
[
{
"id": "f72d85c5e090800f",
"type": "tab",
"label": "Test",
"disabled": false,
"info": "",
"env": []
},
{
"id": "1841dfa69e5c3254",
"type": "eth-ip in",
"z": "f72d85c5e090800f",
"endpoint": "96b408201848d104",
"mode": "all",
"variable": "",
"program": "",
"name": "",
"x": 90,
"y": 80,
"wires": [
[]
]
},
{
"id": "96b408201848d104",
"type": "eth-ip endpoint",
"address": "192.168.1.1",
"slot": "0",
"cycletime": "3000",
"timeout": "10000",
"name": "",
"connectedMess": true,
"vartable": {
"": {
"CYCLES_VEHICLE_1": {
"type": "DINT"
},
"CYCLES_VEHICLE_2": {
"type": "DINT"
},
"ERROR": {
"type": "DINT"
},
"STATUS": {
"type": "DINT"
}
}
}
}
]
I just updated the post. I forgot to include a sample flow.
See Types : Node-RED for what you should be posting, I think.
The payload format for updating an individual tab is different.
The API docs give an example of the format, but if in doubt, do a GET to the same URL to see the format.
Doing a GET returns the content of the flow, the same content that is in my JSON export of the tab in NR. Isn't that what I'm supposed to be sending to NR?
curl -H "Authorization: Bearer ${TOKEN}" -X GET http://${IP}:1880/flow/f72d85c5e090800f
{"id":"f72d85c5e090800f","label":"Test","disabled":false,"info":"","env":[],"nodes":[{"id":"1841dfa69e5c3254","type":"eth-ip in","z":"f72d85c5e090800f","endpoint":"96b408201848d104","mode":"all","variable":"","program":"","name":"","x":90,"y":80,"wires":[[]]}]}
The format is different.
You are posting an array of nodes. The API expects a single object that is the tab
object, that has a nodes
property containing the array of nodes on the flow.
If I'm understanding correctly, I can't simply export a tab and use that file as-is. I have to modify it to match a different format?
In other words, turn this:
[
{
"id": "f72d85c5e090800f",
"type": "tab",
"label": "Test",
"disabled": false,
"info": "",
"env": []
},
{
"id": "1841dfa69e5c3254",
"type": "eth-ip in",
"z": "f72d85c5e090800f",
"endpoint": "96b408201848d104",
"mode": "all",
"variable": "",
"program": "",
"name": "",
"x": 90,
"y": 80,
"wires": [
[]
]
},
{
"id": "96b408201848d104",
"type": "eth-ip endpoint",
"address": "192.168.1.1",
"slot": "0",
"cycletime": "3000",
"timeout": "10000",
"name": "",
"connectedMess": true,
"vartable": {
"": {
"CYCLES_VEHICLE_1": {
"type": "DINT"
},
"CYCLES_VEHICLE_2": {
"type": "DINT"
},
"ERROR": {
"type": "DINT"
},
"STATUS": {
"type": "DINT"
}
}
}
}
]
into this?
{
"id": "f72d85c5e090800f",
"label": "Test",
"nodes": [{
"id": "1841dfa69e5c3254",
"type": "eth-ip in",
"z": "f72d85c5e090800f",
"endpoint": "96b408201848d104",
"mode": "all",
"variable": "",
"program": "",
"name": "",
"x": 90,
"y": 80,
"wires": [
[]
]
},
{
"id": "96b408201848d104",
"type": "eth-ip endpoint",
"address": "192.168.1.1",
"slot": "0",
"cycletime": "3000",
"timeout": "10000",
"name": "",
"connectedMess": true,
"vartable": {
"": {
"CYCLES_VEHICLE_1": {
"type": "DINT"
},
"CYCLES_VEHICLE_2": {
"type": "DINT"
},
"ERROR": {
"type": "DINT"
},
"STATUS": {
"type": "DINT"
}
}
}
}],
"configs": [ ]
}
Yes. As described in the docs, the /flow
endpoint uses a slightly different format, but the translation between them is fairly straightforward.
To be sure I understand...
I need to export that tab of my flow and then modify the file before trying to update it on the remote Pi using curl? I ask because NR didn't like that either. Then it hit me that I needed to set the parameters (id, label, nodes, configs) in curl so I did that...
TEST=$(<Test.json)
curl --header "Content-Type: application/json" --request POST --data '{"id":"f72d85c5e090800f","type":"tab","label":"Test","nodes":"${TEST}","configs":[],"subflows":[]}' -H "Authorization: Bearer ${TOKEN}" -X PUT http://${IP}:1880/flow/f72d85c5e090800f
...and was presented with a nice little red box in NR when I opened it.
Error adding flows
f.type is undefined
Without knowing what was in Test.json, it's hard to say what has happened.
Did you remove the tab
node from the export before adding it in the nodes
array?
Test.json is what was downloaded from NR when I exported the tab. I tried it both as downloaded (when the edited version failed) and also the edited version you said I needed it changed to.
Original Test.json:
[
{
"id": "f72d85c5e090800f",
"type": "tab",
"label": "Test",
"disabled": false,
"info": "",
"env": []
},
{
"id": "1841dfa69e5c3254",
"type": "eth-ip in",
"z": "f72d85c5e090800f",
"endpoint": "96b408201848d104",
"mode": "all",
"variable": "",
"program": "",
"name": "",
"x": 90,
"y": 80,
"wires": [
[]
]
},
{
"id": "96b408201848d104",
"type": "eth-ip endpoint",
"address": "192.168.1.1",
"slot": "0",
"cycletime": "3000",
"timeout": "10000",
"name": "",
"connectedMess": true,
"vartable": {
"": {
"CYCLES_VEHICLE_1": {
"type": "DINT"
},
"CYCLES_VEHICLE_2": {
"type": "DINT"
},
"ERROR": {
"type": "DINT"
},
"STATUS": {
"type": "DINT"
}
}
}
}
]
Edited Test.json (also failed):
{
"id": "f72d85c5e090800f",
"label": "Test",
"nodes": [{
"id": "1841dfa69e5c3254",
"type": "eth-ip in",
"z": "f72d85c5e090800f",
"endpoint": "96b408201848d104",
"mode": "all",
"variable": "",
"program": "",
"name": "",
"x": 90,
"y": 80,
"wires": [
[]
]
},
{
"id": "96b408201848d104",
"type": "eth-ip endpoint",
"address": "192.168.1.1",
"slot": "0",
"cycletime": "3000",
"timeout": "10000",
"name": "",
"connectedMess": true,
"vartable": {
"": {
"CYCLES_VEHICLE_1": {
"type": "DINT"
},
"CYCLES_VEHICLE_2": {
"type": "DINT"
},
"ERROR": {
"type": "DINT"
},
"STATUS": {
"type": "DINT"
}
}
}
}],
"configs": [ ]
}
You have not responded to my suggestion that you use environment variables to configure the different machines, thereby removing the necessity for doing any of this.
Rest assured I'm also looking into that. I'm trying to figure out how I would implement environment variables in node-red-contrib-cip-st-ethernet-ip, node-red-contrib-dde, node-red-contrib-pccc, and node-red-contrib-s7.
If I used environment variables and just deployed the entire flow to deploy updates, wouldn't that delete my configuration nodes on the target?
You would set the environment variables outside of Node-RED - unique to each device. So when Node-RED starts is reads the local environment and sets the required fields as appropriate. see Using environment variables : Node-RED
No, as Dave said, in any node you can put ${ENV_VAR}
in the nodes config fields, and it will use whatever is in that environment variable.
Very good and thank you. I did try that earlier and it works well for the endpoint configuration in an ethip-in node but it does not work for the tags I need to read. Even then, I won't be monitoring the same number of tags or addresses on each machine. That's why you'll see in the following screenshots I created "BLANK" with nothing there to see how the node would react to that. I was expecting it to read the first two tags fine and generate an error on the third.
Perhaps @ machadotiago can chime in on what to do there.
As far as updating individual tabs, I give up. The documentation IS lacking on that front. Simple examples in documentation go a long way. If I wasn't able to figure it out by now it's not worth the effort and it sure looks like using environment variables is out the door, too.
I would really have preferred using environment variables but it doesn't appear ST-One's node's support them. I hope I'm wrong because I'm stuck doing updates the long way (about 50 pieces of equipment, more in the future) if they don't.