IVAO RWY Separator tool
Features:
- Zoom and select in Aurora by clicking flight.
- Adding to separation queue with one click.
- Separation by wake turbulence and performance combined.
- Timer counter for each flight.
Limitations:
- No intersection departure yet.
- No taking into account military jets yet.
- Bugs here and there.
Steps to install:
- Download the FAA aircraft database at https://www.faa.gov/airports/engineering/aircraft_char_database/aircraft_data, export it to CSV with name aircraft_data.csv and put it in the folder
C:\Users\%USERPROFILE%
- Install Node-RED following steps 1, 2 and 3 here https://nodered.org/docs/getting-started/windows
- Import this flow by pressing Copy JSON below, the go to the dashboard on a browser at http://localhost:1880/ (preferably not with Edge), Menu --> Import and paste it there.
- Activate in Aurora in Settings --> Other --> 3rd Party software access
- Have fun at http://localhost:1880/dashboard/page1
Steps to use the program:
Program is quite intuitive:
- Click on the rows of the left table to zoom in Aurora.
- Click on the flight callsign to add it to the separation table.
- Click on the callsign on the right table to initiate the countdown timer for departure.
Do not sort flights on the right table, it will get messy.
[{"id":"16edfb01c70b130f","type":"tab","label":"Commands","disabled":false,"info":"","env":[]},{"id":"3146b288e6c76342","type":"tab","label":"Dashboard","disabled":false,"info":"","env":[]},{"id":"5457fd26d6abbbc4","type":"group","z":"16edfb01c70b130f","name":"Collect traffic in range","style":{"label":true},"nodes":["6d66a1d18133051a","df7adf18572e475d","7cfa5d56726162c8","4c4c8a93cf915460"],"x":94,"y":99,"w":1032,"h":82},{"id":"71f1b930d94642b3","type":"group","z":"16edfb01c70b130f","name":"Connected callsign","style":{"label":true},"nodes":["adc75a87d5960bf4","151edc77bfa834b1"],"x":614,"y":639,"w":392,"h":82},{"id":"661594e722965e63","type":"group","z":"16edfb01c70b130f","name":"Create object for \"flights\"","style":{"label":true},"nodes":["96fc07a3f7d5f4e7"],"x":1174,"y":99,"w":162,"h":82},{"id":"2ffce7a8e3e48b2a","type":"group","z":"3146b288e6c76342","name":"Zoom and select","style":{"label":true},"nodes":["37bfb52416f7b1f7","7003121bb23630ac","405c2afd4f399639"],"x":294,"y":599,"w":632,"h":182},{"id":"e32955253ea7b0a5","type":"ui-base","name":"My Dashboard","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"showPageTitle":true,"navigationStyle":"default","titleBarStyle":"default"},{"id":"617a65b2a4100117","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094CE","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"density":"default","pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}},{"id":"cd261eb069541794","type":"ui-page","name":"IVAO RWY Separator tool","ui":"e32955253ea7b0a5","path":"/page1","icon":"home","layout":"grid","theme":"617a65b2a4100117","order":1,"className":"","visible":"true","disabled":false},{"id":"bfd4b65202ce0db8","type":"ui-group","name":"Traffic in range","page":"cd261eb069541794","width":"6","height":"1","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"8d6adaf1f2805cc2","type":"sqlitedb","db":"flights_db","mode":"RWC"},{"id":"1c69d60f6287f228","type":"ui-group","name":"Separation","page":"cd261eb069541794","width":"6","height":"1","order":2,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"adc75a87d5960bf4","type":"inject","z":"16edfb01c70b130f","g":"71f1b930d94642b3","name":"#CONN","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[35,67,79,78,78,13,10]","payloadType":"bin","x":710,"y":680,"wires":[["151edc77bfa834b1"]]},{"id":"151edc77bfa834b1","type":"tcp request","z":"16edfb01c70b130f","g":"71f1b930d94642b3","name":"","server":"localhost","port":"1130","out":"sit","ret":"string","splitc":" ","newline":"\\r\\n","trim":false,"tls":"","x":890,"y":680,"wires":[[]]},{"id":"6d66a1d18133051a","type":"inject","z":"16edfb01c70b130f","g":"5457fd26d6abbbc4","name":"#TR","props":[{"p":"payload"}],"repeat":"5","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"[35,84,82,13,10]","payloadType":"bin","x":190,"y":140,"wires":[["df7adf18572e475d"]]},{"id":"df7adf18572e475d","type":"tcp request","z":"16edfb01c70b130f","g":"5457fd26d6abbbc4","name":"","server":"localhost","port":"1130","out":"sit","ret":"string","splitc":" ","newline":"\\r\\n","trim":false,"tls":"","x":370,"y":140,"wires":[["7cfa5d56726162c8"]]},{"id":"7cfa5d56726162c8","type":"change","z":"16edfb01c70b130f","g":"5457fd26d6abbbc4","name":"Create array","rules":[{"t":"set","p":"payload","pt":"msg","to":"\t$split(payload, \";\")\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":140,"wires":[["4c4c8a93cf915460"]]},{"id":"4c4c8a93cf915460","type":"function","z":"16edfb01c70b130f","g":"5457fd26d6abbbc4","name":"Remove first (command) and last element (new line)","func":"msg.payload.shift();\nmsg.payload.pop();\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":900,"y":140,"wires":[["96fc07a3f7d5f4e7"]]},{"id":"96fc07a3f7d5f4e7","type":"split","z":"16edfb01c70b130f","g":"661594e722965e63","name":"","splt":"","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","property":"payload","x":1250,"y":140,"wires":[["91b12d6f3cc147c4"]]},{"id":"29c8439a871d7f99","type":"function","z":"16edfb01c70b130f","name":"Update flights_data","func":"let oldFlights_data = global.get(\"flights_data\") || {};\nlet faa_data = global.get(\"faa_db\");\n\nlet newFlight_data = msg.payload;\n\n// New information to add or update\nfor (let key in newFlight_data) {\n //let aircraft = faa_data.find(obj => obj.ICAO_Code === newFlight_data[\"Aircraft ICAO\"]);\n \n //let wingspan = aircraft.Wingspan_ft_without_winglets_sharklets || 0;\n //let wingspan_sharklets = aircraft.Wingspan_ft_with_winglets_sharklets || 0;\n //newFlight_data[key].Wingspan = Math.max(wingspan, wingspan_sharklets);\n\n oldFlights_data[key] = newFlight_data[key];\n}\n\n// Remove keys from oldFlights_data that are not in newInformation\nfor (let key in oldFlights_data) {\n if (!(key in newFlight_data)) {\n delete oldFlights_data[key];\n }\n}\n\nglobal.set(\"flights_data\", oldFlights_data);\nreturn;","outputs":1,"timeout":0,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\nglobal.set(\"flights_data\", {});","finalize":"","libs":[],"x":1410,"y":320,"wires":[[]]},{"id":"91b12d6f3cc147c4","type":"template","z":"16edfb01c70b130f","name":"Create FPL query","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"#FP;{{payload}}","output":"str","x":270,"y":240,"wires":[["bc58e8887b42c9b2"]]},{"id":"bc58e8887b42c9b2","type":"function","z":"16edfb01c70b130f","name":"Concatenate buffer to add CR and LF","func":"msg.payload = Buffer.concat([Buffer.from(msg.payload), Buffer.from([13, 10])]);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":240,"wires":[["bf49acdebf38c213"]]},{"id":"bf49acdebf38c213","type":"tcp request","z":"16edfb01c70b130f","name":"","server":"localhost","port":"1130","out":"sit","ret":"string","splitc":" ","newline":"\\r\\n","trim":false,"tls":"","x":830,"y":240,"wires":[["bec40a23aa8452d9"]]},{"id":"bec40a23aa8452d9","type":"change","z":"16edfb01c70b130f","name":"Remove FP part","rules":[{"t":"change","p":"payload","pt":"msg","from":"#FP;","fromt":"str","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1060,"y":240,"wires":[["fc11999560b47f5c"]]},{"id":"fc11999560b47f5c","type":"csv","z":"16edfb01c70b130f","name":"","spec":"rfc","sep":";","hdrin":"","hdrout":"none","multi":"one","ret":"\\r\\n","temp":"Callsign,Departure ICAO,Arriving ICAO,Alternate ICAO,Estimated departure time,Aircraft ICAO,Wake turbulence,Flight type,Flight rules,Equipment,Cruising altitude,Cruising speed,Endurance,Estimated flight time,Route,Remarks","skip":"0","strings":false,"include_empty_strings":true,"include_null_values":true,"x":1230,"y":240,"wires":[["bcb03be68394a81a"]]},{"id":"538e8edbae8eeee5","type":"join","z":"16edfb01c70b130f","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"payload.Callsign","joiner":"\\n","joinerType":"str","useparts":false,"accumulate":false,"timeout":"3","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1110,"y":320,"wires":[["29c8439a871d7f99"]]},{"id":"bcb03be68394a81a","type":"change","z":"16edfb01c70b130f","name":"Remove msg.complete for join to work","rules":[{"t":"delete","p":"complete","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1470,"y":240,"wires":[["538e8edbae8eeee5"]]},{"id":"53147f31d23ccdbb","type":"inject","z":"16edfb01c70b130f","name":"","props":[],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","x":150,"y":480,"wires":[["91ae6115cbb68bad"]]},{"id":"91ae6115cbb68bad","type":"file in","z":"16edfb01c70b130f","name":"","filename":".\\aircraft_data.csv","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":360,"y":540,"wires":[["da60190fdfc23371"]]},{"id":"da60190fdfc23371","type":"csv","z":"16edfb01c70b130f","name":"","spec":"rfc","sep":",","hdrin":true,"hdrout":"none","multi":"mult","ret":"\\r\\n","temp":"","skip":"0","strings":true,"include_empty_strings":true,"include_null_values":true,"x":730,"y":540,"wires":[["368883b42b86776a"]]},{"id":"368883b42b86776a","type":"change","z":"16edfb01c70b130f","name":"","rules":[{"t":"set","p":"faa_db","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":910,"y":540,"wires":[[]]},{"id":"3a0a00dc0fb53ff2","type":"status","z":"16edfb01c70b130f","name":"","scope":["df7adf18572e475d"],"x":140,"y":360,"wires":[["0b1b6eae2cd3518c"]]},{"id":"9389bc1e4263da87","type":"ui-text","z":"16edfb01c70b130f","group":"1c69d60f6287f228","order":3,"width":0,"height":0,"name":"Status connection","label":"Status connection to Aurora: ","format":"{{msg.payload}}","layout":"row-left","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":570,"y":360,"wires":[]},{"id":"4bbc41627d1e2a18","type":"switch","z":"16edfb01c70b130f","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"common.status.disconnected","vt":"str"},{"t":"eq","v":"1 connection","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":370,"y":420,"wires":[["0241fa8285e82311"],["bca8d7e8f5b12790"],[]]},{"id":"0b1b6eae2cd3518c","type":"change","z":"16edfb01c70b130f","name":"","rules":[{"t":"move","p":"status.text","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":200,"y":420,"wires":[["4bbc41627d1e2a18"]]},{"id":"0241fa8285e82311","type":"change","z":"16edfb01c70b130f","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"No funca","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":400,"wires":[["9389bc1e4263da87"]]},{"id":"bca8d7e8f5b12790","type":"change","z":"16edfb01c70b130f","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"A tope!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":440,"wires":[["9389bc1e4263da87"]]},{"id":"6d8c61e2815579a7","type":"ui-table","z":"3146b288e6c76342","group":"bfd4b65202ce0db8","name":"Traffic in range","label":"text","order":1,"width":0,"height":0,"maxrows":0,"passthru":false,"autocols":false,"showSearch":true,"selectionType":"click","columns":[{"title":"Callsign","key":"Callsign","type":"button","width":"1","align":"start"},{"title":"Wake turbulence","key":"Wake turbulence","type":"text","width":"1","align":"start"},{"title":"Aircraft ICAO","key":"Aircraft ICAO","type":"text","width":"1","align":"start"},{"title":"Flight type","key":"Flight type","type":"text","width":"1","align":"start"},{"title":"Departure ICAO","key":"Departure ICAO","type":"text","width":"1","align":"start"}],"mobileBreakpoint":"sm","mobileBreakpointType":"defaults","x":540,"y":240,"wires":[["2621c39fa7a8efc6"]]},{"id":"727210a60f565a6a","type":"ui-table","z":"3146b288e6c76342","group":"1c69d60f6287f228","name":"Separation traffics","label":"text","order":1,"width":0,"height":0,"maxrows":0,"passthru":false,"autocols":false,"showSearch":false,"selectionType":"none","columns":[{"title":"Number","key":"","type":"row","width":"0.1","align":"start"},{"title":"Callsign","key":"Callsign","type":"button","width":"1","align":"start"},{"title":"Ready status","key":"Color","type":"color","width":"","align":"start"},{"title":"Wake turbulence cat","key":"Wake turbulence","type":"text","width":"1","align":"start"},{"title":"Intersection departure","key":"Intersection departure","type":"tickcross","width":"1","align":"start"},{"title":"Wake timer","key":"Wake timer","type":"text","width":"1","align":"start"},{"title":"Flight type","key":"Flight type","type":"text","width":"1","align":"start"},{"title":"Performance cat","key":"Performance cat","type":"text","width":"1","align":"start"},{"title":"Performace timer","key":"Perf timer","type":"text","width":"1","align":"start"},{"title":"Progress","key":"Progress","type":"progress","width":"1","align":"start"},{"title":"Time remaining","key":"Timer","type":"text","width":"1","align":"start"},{"title":"Remove","key":"Remove","type":"button","width":"","align":"start"}],"mobileBreakpoint":"sm","mobileBreakpointType":"defaults","x":1010,"y":260,"wires":[["8f7698139aaf88b9","c7d87e43121ae0e7"]]},{"id":"e2dc81b97a40bad7","type":"inject","z":"3146b288e6c76342","name":"","props":[{"p":"payload"}],"repeat":"3","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"flights_data","payloadType":"global","x":130,"y":240,"wires":[["85a2de3d85c2a0ab"]]},{"id":"85a2de3d85c2a0ab","type":"split","z":"3146b288e6c76342","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","property":"payload","x":150,"y":340,"wires":[["d3b5c1ee1553554a"]]},{"id":"d3b5c1ee1553554a","type":"join","z":"3146b288e6c76342","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","useparts":true,"accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":350,"y":360,"wires":[["6d8c61e2815579a7"]]},{"id":"2621c39fa7a8efc6","type":"switch","z":"3146b288e6c76342","name":"","property":"action","propertyType":"msg","rules":[{"t":"eq","v":"button_click","vt":"str"},{"t":"eq","v":"row_click","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":510,"y":500,"wires":[["c49b16f69e3bd35f"],["7003121bb23630ac"]]},{"id":"c49b16f69e3bd35f","type":"function","z":"3146b288e6c76342","name":"Add traffic to separation table","func":"let separation_table = global.get(\"separation_table\") || [];\nlet faa_db = global.get(\"faa_db\");\n\n//Add number\n//Calculate wake turbulence timer\nlet wake_actual = msg.payload[\"Wake turbulence\"];\nif (separation_table.length >= 1) {\n let wake_previous = separation_table[separation_table.length - 1][\"Wake turbulence\"];\n var wake_timer;\n\n if (wake_actual == \"L\" && wake_previous == \"M\")\n {\n wake_timer = 120;\n }\n \n else if ((wake_actual == \"L\" || wake_actual == \"M\") && wake_previous == \"H\")\n {\n wake_timer = 120;\n }\n\n else if ((wake_actual == \"L\" || wake_actual == \"M\") && wake_previous == \"S\")\n {\n wake_timer = 180;\n }\n\n else wake_timer = 0;\n} else wake_timer = 0;\nmsg.payload[\"Wake timer\"] = wake_timer;\n\n//Calculate performance timer\nlet aircraft = faa_db.find(obj => obj.ICAO_Code === msg.payload[\"Aircraft ICAO\"]);\nlet performance_cat = aircraft.Physical_Class_Engine;\nmsg.payload[\"Performance cat\"] = performance_cat;\n\nlet perf_actual = msg.payload[\"Performance cat\"];\nif (separation_table.length >= 1) {\n \n let perf_previous = separation_table[separation_table.length - 1][\"Performance cat\"];\n \n let index = separation_table.length - 1;\n let foundIndex = -1;\n\n while (index >= 0) {\n if (separation_table[index][\"Flight Type\"] === \"I\" || \"Y\") {\n foundIndex = index;\n break;\n }\n index--;\n }\n\n if (foundIndex !== -1) {\n perf_previous = separation_table[foundIndex][\"Performance cat\"];\n } else {\n perf_previous = \"FREE\";\n }\n \n var perf_timer;\n\n if (perf_actual == \"Military\") {\n perf_timer = \"HELD/SUJETA\";\n }\n\n else if (perf_previous == \"Military\") {\n perf_timer = 120;\n }\n\n else if (perf_actual == \"Jet\" && perf_previous == \"Jet\") {\n perf_timer = 120;\n }\n\n else if ((perf_actual == \"Piston\" || perf_actual == \"Turboprop\") && perf_previous == \"Jet\") {\n perf_timer = 90;\n }\n\n else if (perf_actual == \"Jet\" && perf_previous == \"Turboprop\") {\n perf_timer = \"HELD/SUJETA\";\n }\n\n else if (perf_actual == \"Turboprop\" && perf_previous == \"Turboprop\") {\n perf_timer = 120;\n }\n\n else if (perf_actual == \"Piston\" && perf_previous == \"Turboprop\") {\n perf_timer = 90;\n }\n\n else if (perf_previous == \"Piston\") {\n perf_timer = \"HELD/SUJETA\";\n }\n\n else if (perf_previous == \"FREE\") {\n perf_timer = 0;\n }\n\n else {\n perf_timer = \"ERROR\";\n }\n} else perf_timer = 0;\nmsg.payload[\"Perf timer\"] = perf_timer;\n\n//Intersection departure bool\n//Add progress bar?\n//Timer remaining\nlet timer = Math.max(wake_timer, perf_timer);\nmsg.payload[\"Timer\"] = timer;\n\n//Counting time bool\nmsg.payload[\"is_counting\"] = false;\n\n//Adding color\nif (perf_timer == \"HELD/SUJETA\") \n {\n msg.payload[\"Color\"] = \"#FF0000\"\n } else if (timer == 0) {\n msg.payload[\"Color\"] = \"#00FF00\"\n } else {\n msg.payload[\"Color\"] = \"#FFFFFF\";\n }\n\nseparation_table.push(msg.payload);\n\nglobal.set(\"separation_table\", separation_table)\nreturn;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":820,"y":500,"wires":[[]]},{"id":"1dc8f8136dab6fa5","type":"inject","z":"3146b288e6c76342","name":"","props":[{"p":"payload"}],"repeat":"2","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"separation_table","payloadType":"global","x":870,"y":200,"wires":[["727210a60f565a6a"]]},{"id":"11eaf7fa952246ba","type":"comment","z":"3146b288e6c76342","name":"Avoid duplicates to be implemented?","info":"","x":820,"y":460,"wires":[]},{"id":"cc92634ce70a9566","type":"ui-button","z":"3146b288e6c76342","group":"1c69d60f6287f228","name":"Empty list","label":"Empty list","order":2,"width":"1","height":"1","emulateClick":false,"tooltip":"","color":"","bgcolor":"","className":"","icon":"","iconPosition":"left","payload":"","payloadType":"str","topic":"topic","topicType":"msg","buttonColor":"red","textColor":"","iconColor":"","x":1340,"y":520,"wires":[["d5edd88347377e5b"]]},{"id":"d5edd88347377e5b","type":"change","z":"3146b288e6c76342","name":"","rules":[{"t":"delete","p":"separation_table","pt":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":1570,"y":520,"wires":[[]]},{"id":"8f7698139aaf88b9","type":"function","z":"3146b288e6c76342","name":"Remove row","func":"if (msg.action == \"button_click\" && msg.column == \"Remove\"){\n\n let separation_table = global.get(\"separation_table\");\n let callsign_to_remove = msg.payload[\"Callsign\"];\n let index = separation_table.findIndex(flight => flight[\"Callsign\"] === callsign_to_remove);\n\n separation_table.splice(index, 1);\n \n global.set(\"separation_table\", separation_table);\n}\n\nreturn;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1330,"y":360,"wires":[[]]},{"id":"dae965fdb705135a","type":"function","z":"3146b288e6c76342","name":"Count every second, update color, progress and boolean","func":"let separation_table = global.get(\"separation_table\");\n\n//Loop through all elements\nseparation_table.forEach((element, index, array) => {\n \n if (element.is_counting == true && element[\"Timer\"] > 0) {\n element[\"Timer\"]--;\n element[\"Color\"] = \"#FFFF00\"; //Yellow\n element[\"Progress\"] = Math.round((element[\"Timer\"] / Math.max(element[\"Wake timer\"], element[\"Perf timer\"]))*100);\n //Assess if finished\n if (element[\"Timer\"] == 0){\n element.is_counting = false\n element[\"Color\"] = \"#00FF00\"; //Green\n element[\"Progress\"] = 0;\n }\n }\n array[index] = element;\n});\n//Update time\n//Update color\n//Update boolean if finished\n\nglobal.set(\"separation_table\", separation_table);\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1470,"y":440,"wires":[[]]},{"id":"18e805a2df931d1e","type":"inject","z":"3146b288e6c76342","name":"","props":[],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1130,"y":440,"wires":[["dae965fdb705135a"]]},{"id":"c7d87e43121ae0e7","type":"function","z":"3146b288e6c76342","name":"Activate counter","func":"if (msg.action == \"button_click\" && msg.column == \"Callsign\"){\n\n let separation_table = global.get(\"separation_table\");\n let callsign_to_start = msg.payload[\"Callsign\"];\n let index = separation_table.findIndex(flight => flight[\"Callsign\"] === callsign_to_start);\n\n if (separation_table[index][\"Timer\"] > 0) separation_table[index][\"Progress\"] = 100;\n separation_table[index].is_counting = true;\n\n global.set(\"separation_table\", separation_table);\n\n}\n\nreturn;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1340,"y":400,"wires":[[]]},{"id":"37bfb52416f7b1f7","type":"tcp request","z":"3146b288e6c76342","g":"2ffce7a8e3e48b2a","name":"","server":"localhost","port":"1130","out":"sit","ret":"string","splitc":" ","newline":"\\r\\n","trim":false,"tls":"","x":770,"y":740,"wires":[[]]},{"id":"7003121bb23630ac","type":"template","z":"3146b288e6c76342","g":"2ffce7a8e3e48b2a","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"#ZSTR;{{payload.Callsign}}","output":"str","x":840,"y":640,"wires":[["405c2afd4f399639"]]},{"id":"405c2afd4f399639","type":"function","z":"3146b288e6c76342","g":"2ffce7a8e3e48b2a","name":"Concatenate buffer to add CR and LF","func":"msg.payload = Buffer.concat([Buffer.from(msg.payload), Buffer.from([13, 10])]);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":740,"wires":[["37bfb52416f7b1f7"]]},{"id":"6ac56c7d1ce5fb8f","type":"comment","z":"3146b288e6c76342","name":"Intersection to be implemented","info":"","x":1387.5999755859375,"y":246.1999969482422,"wires":[]}]