node-red-contrib-tfr2cot
Version:
If msg.payload or env.tfrStatesList is a json formatted array of 2 letter U.S. abbreviation for states as a text strings, this node returns a msg.payload as JSON cursor-on-target (CoT) message for use with node-red-contrib-tak node and tcp out node.
26 lines • 6.72 kB
JSON
[
{
"id": "03edc968b374595f",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "NOTAM cot_attrib",
"func": "const payload = msg.payload;\nconst tfr_dict = payload[\"XNOTAM-Update\"].Group[0].Add[0].Not[0];\nconst tfr_info = tfr_dict.TfrNot[0].TFRAreaGroup;\n\nconst cot_attrib_template = {\n \"how\": \"h-e\", //h-g-i-g-o, etc\n \"type\": \"u-d-f\",//\"a-u-G\"\n \"lat\": parseFloat(\"0.0\"),\n \"lon\": parseFloat(\"0.0\"),\n \"altitude\": parseFloat(\"9999999.0\"),\n \"callsign\": \"\",\n \"uid\": \"\",\n \"stale\": \"\",\n \"detail\": {\n \"cot2525\": \"a-h-G\",\n \"marker_color\": \"-1\",\n \"pli\": {\n \"groupName\": null,\n \"role\": null,\n \"phone\": null,\n },\n \"dest\": {\n \"uid\": \"ANDROID-1c2680c542b6c9f6\",\n \"mission\": null,\n \"callsign\": null\n },\n \"link\": {\n \"url\": null,\n \"remarks\": null,\n \"uid\": \"nodered\",\n \"parent_callsign\": \"Some callsign from NodeRED\",\n \"production_time\": \"\"\n },\n \"remarks\": \"\",\n \"marker\": {\n \"iconsetpath\": \"\",\n \"color\": \"\"\n },\n \"shape\": {\n \"distance\": null,\n \"color\": \"-65536\",\n \"LineStyle\": {\n \"color\": \"ff0000\", //hex e.g.\"ffff0000\"\n \"width\": \"1.0\", //3.0\n },\n \"PolyStyle\": {\n \"color\": \"ff0000\", //hex e.g.\"ffff0000\"\n },\n \"strokecolor\": \"-65536\", //value='-65536'/>\n \"strokeweight\": \"1.0\",//'3.0'\n \"fillColor\": \"\", //value='16711680\n \"labels_on\": \"true\" //value = \"true\" or \"false\"\n },\n \"callsign\": \"\",\n \"height\": null\n }\n};\nfor (var i = 0; i < tfr_info.length; i++){\n /*var coordinatesA = tfr_info[i].abdMergedArea[0].Avx;\n\n var coordinates = [];\n var x = 0;\n var y = 0;\n for (var j = 0; j < coordinatesA.length; j++) {\n var coordinate = coordinatesA[j].split(',');\n x += parseFloat(coordinate[1]);\n y += parseFloat(coordinate[0]);\n }\n var centroid = {\n 'lat': (x / coordinates.length).toString(),\n 'lon': (y / coordinates.length).toString()\n };*/\n\n const tfr_id = tfr_dict.NotUid[0].codeGUID[0];//txtLocalName[0].replace(\"/\", \"_\");\n var tfr_base_label = \"3-\"+tfr_dict.NotUid[0].noSeqNo[0];\n //var url = \"https://tfr.faa.gov/save_pages/detail_\"+tfr_id+\".html\";\n var url = msg.url.replace(\"xml\",\"html\")\n var remarks = tfr_dict.txtDescrTraditional[0];\n if (i >= 1) {\n var label_area = tfr_info[i].aseTFRArea[0].txtName[0]\n } else {\n label_area = \"\";\n }\n \n //Get Local Times (AZ = UTC - 7)\n /*const utcOffset = -7;\n var scheduleGroup = tfr_info[i].aseTFRArea[0].ScheduleGroup[0];\n\n var dateEffectiveStr = scheduleGroup.dateEffective[0];//+\".0Z\";\n var dateEffectiveUtc = new Date(dateEffectiveStr);\n var dateEffectiveLocal = new Date(dateEffectiveUtc.getTime() + utcOffset * 60 * 60 * 1000);\n\n var dateExpireStr = scheduleGroup.dateExpire[0];// + \".0Z\";\n var dateExpireUtc = new Date(dateExpireStr);\n var dateExpireLocal = new Date(dateExpireUtc.getTime() + utcOffset * 60 * 60 * 1000);\n if (scheduleGroup.isTimeSeparate === \"TRUE\") {\n var startTimeStr = scheduleGroup.startTime[0];// + \".0Z\";\n var startTimeUtc = new Date(startTimeStr);\n var startTimeLocal = new Date(startTimeUtc.getTime() + utcOffset * 60 * 60 * 1000);\n\n var endTimeStr = scheduleGroup.endTime[0];// + \".0Z\";\n var endTimeUtc = new Date(endTimeStr);\n var endTimeLocal = new Date(endTimeUtc.getTime() + utcOffset * 60 * 60 * 1000);\n } else {\n startTimeLocal = \"\";\n endTimeLocal = \"\";\n };*/\n\n var cot_attrib = cot_attrib_template;\n cot_attrib.callsign = (\"tfr-\"+tfr_base_label+\" \"+label_area).trim();\n cot_attrib.detail.callsign = (\"tfr-\" + tfr_base_label + \" \" + label_area).trim();\n cot_attrib.uid = (tfr_id+\" \"+label_area).trim();//\"tfr.\"+tfr_id.replace(\"_\",\"-\");\n cot_attrib.detail.remarks = remarks;\n cot_attrib.detail.link.url = url;\n //cot_attrib.detail.link.remarks = \"Date Effective: \" + dateEffectiveLocal.toLocaleDateString() + \"\\nExpired: \" + dateExpireLocal.toLocaleDateString() + \"\\nStart Time: \" + startTimeLocal.toLocaleTimeString() + \"\\nEnd Time: \" + endTimeLocal.toLocaleTimeString();\n //cot_attrib.detail.link.production_time = scheduleGroup.dateEffective[0]+\".0Z\";\n\n //GET COORDINATES & ALTITUDE:\n let kml_coordinates = tfr_info[i].aseShapes[0].Abd[0].Avx[0];\n cot_attrib.lat = parseFloat(kml_coordinates.geoLat[0].replace(\"N\",\"\"));\n cot_attrib.lon = parseFloat(\"-\"+kml_coordinates.geoLong[0].replace(\"W\",\"\"));\n let height = parseFloat(tfr_info[i].aseTFRArea[0].valDistVerUpper[0]);\n if (height !== undefined && height !== null) {\n cot_attrib.detail.height = parseFloat(tfr_info[i].aseTFRArea[0].valDistVerUpper[0]) * 0.3048;\n };\n //Get Link Points:\n var linkPoints = tfr_info[i].abdMergedArea[0].Avx;\n var link_points = [];\n for (var j=0;j < linkPoints.length; j++) {\n link_points[j] = linkPoints[j].geoLat[0].replace(\"N\", \"\") + \",-\" + linkPoints[j].geoLong[0].replace(\"W\", \"\")\n };\n\n // Function to process each line and reverse [0] and [1] while deleting [2]\n function processLine(line) {\n var coords = line.split(\",\");\n return [parseFloat(coords[0]), parseFloat(coords[1])];\n }\n\n // Map the lines array to process each line\n var link_points_list = link_points.map(processLine);\n\n var links = link_points_list.map(function (item) {\n // Convert the array of coordinates to a string\n var coordinateString = item.join(\",\");\n // Use this string as the key in the new object\n return { [\"_attributes\"]: { \"point\": coordinateString } };\n });\n};\n\nmsg.payload = cot_attrib;\nmsg.linkPoints = { \"link\": links };\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [
{
"var": "axios",
"module": "axios"
}
],
"x": 300,
"y": 300,
"wires": [
[
"8f75d304e5f11f38"
]
]
}
]