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.
674 lines (673 loc) • 57.5 kB
JSON
{
"id": "70eb72484ca97dd5",
"type": "subflow",
"name": "tfr2cot",
"info": "If `msg.payload` or `env.tfrStatesList` is an array of 2 letter U.S. abbreviation text strings for states, 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.\n\n### INPUT\n\n: payload (json) : An array containing a 2-letter abbreviations for the desired U.S. state. If no message or if `msg.payload` is a blank, all TFRs will be downloaded.\n\n### OUTPUTS\n\n1. Standard Output\n: payload (json) : contains a JSON CoT message and should be passed to a `node-red-contrib-tak` node followed by a `tcp out` node with the appropriate network configuration for your set up. See `node-red-contrib-tak` [documentation](https://node-red-contrib-tak.readthedocs.io/en/latest/) for further details.\n\n2. [TAK Server](https:///tak.gov) DataSync Outputs (Optional)\n: payload (json) : a json object with the CoT UID sent to the TAK Server in Output #1\n: url (string) : Contains the http PUSH url using the `.takServerUrl` and `.missionApiPort` (typically `8443`). It will not send anything if these properties are left blank.\n: header (json) : Contans the header needed to interact with the TAK Server API.\n: method (string): `PUT` to pass the cotUid to DataSync to include the CoT message sent out in Output #1.\n\n 4 Messages are pushed if you are sending your CoT messages to a specific DataSync Mission:\n\n > NOTE that prior to these messages going out, you need to be sending an SA Message along with subscribing to that mission. You also need an `http request` node properly configured as the recipient of these messages. Please See the `DataSync Subscription` and `http request` node configuration for more.\n\n > *If any of the properties: `.creatorUid`, `.takServerUrl`, `.takMission` are empty and/or the `.missionApiPort` is not set correctly (it is set to 8443 by default), there will be no message from Output #2.\n\n3. Debug Node (beta) to determine parsing errors.\n\n### DETAILS\n**Example JSON CoT message:**\n```json\n{\n \"event\": {\n \"_attributes\": {\n \"version\": \"2.0\",\n \"uid\": \"10c46aff-3007-439a-9ee1-fc5ca256395b\",\n \"type\": \"u-d-f\",\n \"how\": \"h-e\",\n \"time\": \"2023-08-15T10:35:21.131Z\",\n \"start\": \"2023-08-15T10:35:21.131Z\",\n \"stale\": \"2023-08-15T10:55:21.131Z\"\n },\n \"point\": {\n \"_attributes\": {\n \"lat\": \"39.13416667\",\n \"lon\": \"-121.4375\",\n \"hae\": \"9999999.0\",\n \"ce\": \"9999999.0\",\n \"le\": \"9999999.0\"\n }\n },\n \"detail\": {\n \"strokeColor\": [\n {\n \"_attributes\": {\n \"value\": \"-65536\"\n }\n }\n ],\n \"strokeWeight\": [\n {\n \"_attributes\": {\n \"value\": \"1.0\"\n }\n }\n ],\n \"fillColor\": [\n {\n \"_attributes\": {}\n }\n ],\n \"contact\": [\n {\n \"_attributes\": {\n \"callsign\": \"tfr-3-3868\"\n }\n }\n ],\n \"remarks\": \"!FDC 3/3868 ZOA CA..AIRSPACE BEALE AFB, CA..TEMPORARY FLIGHT RESTRICTIONS. AUGUST 16-NOVEMBER 5, 2023 LOCAL. PURSUANT TO 49 USC 40103(B)(3), THE FEDERAL AVIATION ADMINISTRATION (FAA) CLASSIFIES THE AIRSPACE DEFINED IN THIS NOTAM AS 'NTL DEFENSE AIRSPACE'. ANY PERSON WHO KNOWINGLY OR WILLFULLY VIOLATES THE RULES CONCERNING OPS IN THIS AIRSPACE MAY BE SUBJECT TO CERTAIN CRIMINAL PENALTIES UNDER 49 USC 40103(B)(3). PILOTS WHO DO NOT ADHERE TO THE FOLLOWING PROC MAY BE INTERCEPTED, DETAINED AND INTERVIEWED BY LAW ENFORCEMENT/SECURITY PERSONNEL. \\nPURSUANT TO 14 CFR 99.7, SPECIAL SECURITY INSTRUCTIONS, ALL ACFT FLT OPS ARE PROHIBITED: WI AN AREA DEFINED AS 10NM RADIUS OF 390803N1212615W (MYV055006.7) 4100FT MSL-FL180 EFFECTIVE 2308162200 UTC (1500 LOCAL 08/16/23) UNTIL 2311050859 UTC (0159 LOCAL 11/05/23). EXC AS SPECIFIED BLW AND/OR UNLESS AUTH BY ATC: 1. ALL AIRCRAFT ENTERING OR EXITING THE TFR MUST BE ON A DISCRETE CODE ASSIGNED BY AN AIR TRAFFIC CONTROL (ATC) FACILITY. 2. AIRCRAFT MUST B...\",\n \"labels_on\": [\n {\n \"_attributes\": {\n \"value\": \"true\"\n }\n }\n ],\n \"precisionlocation\": [\n {\n \"_attributes\": {\n \"altsrc\": \"???\"\n }\n }\n ],\n \"color\": [\n {\n \"_attributes\": {\n \"argb\": \"-65536\"\n }\n }\n ],\n \"height\": [\n {\n \"_attributes\": {\n \"value\": \"54.864000000000004\"\n }\n }\n ],\n \"_geofence\": [\n {\n \"_attributes\": {\n \"elevationMonitored\": \"true\",\n \"minElevation\": \"0.0\",\n \"monitor\": \"All\",\n \"trigger\": \"Both\",\n \"tracking\": \"false\",\n \"maxElevation\": \"54.864000000000004\",\n \"boundingSphere\": \"96000.0\"\n }\n }\n ],\n \"link\": [\n {\n \"_attributes\": {\n \"point\": \"39.30098401,-121.4375\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.29844376,-121.4002184\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.29090073,-121.36407744\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.27858565,-121.33018217\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.26187506,-121.29956756\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.24127959,-121.27316653\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.21742807,-121.25178121\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.19104811,-121.23605861\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.16294355,-121.22647129\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.13396987,-121.22330366\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.1050079,-121.22664414\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.07693711,-121.23638347\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.05060886,-121.25221889\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.0268208,-121.27366425\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.00629284,-121.30006528\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"38.9896457,-121.33061985\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"38.97738234,-121.36440231\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"38.96987307,-121.40039125\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"38.96734455,-121.4375\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"38.96987307,-121.47460875\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"38.97738234,-121.51059769\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"38.9896457,-121.54438015\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.00629284,-121.57493472\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.0268208,-121.60133575\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.05060886,-121.62278111\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.07693711,-121.63861653\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.1050079,-121.64835586\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.13396987,-121.65169634\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.16294355,-121.64852871\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.19104811,-121.63894139\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.21742807,-121.62321879\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.24127959,-121.60183347\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.26187506,-121.57543244\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.27858565,-121.54481783\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.29090073,-121.51092256\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.29844376,-121.4747816\"\n }\n },\n {\n \"_attributes\": {\n \"point\": \"39.30098401,-121.4375\"\n }\n },\n {\n \"_attributes\": {\n \"url\": \"https://tfr.faa.gov/save_pages/detail_3_3868.html\",\n \"type\": \"\",\n \"remarks\": null,\n \"relation\": \"r-u\",\n \"mime\": \"text/html\",\n \"version\": \"1.0\",\n \"production_time\": \"\"\n }\n }\n ]\n }\n }\n}\n```\n### References\n 1. [node-red-contrib-tak](): Documentation for installing `node-red-contrib-tak` node with additional information to configure `tcp out` nodes to pass CoT messages to a [TAK Server](https://tak.gov) or network.\n 2. [Team Awareness Kit](https://tak.gov): To learn more of the Team Awareness Kit (TAK) situational awareness platform.\n",
"category": "",
"in": [
{
"x": 110,
"y": 180,
"wires": [
{
"id": "dc36ca9308973733"
},
{
"id": "641fddac886c2429"
}
]
}
],
"out": [
{
"x": 900,
"y": 660,
"wires": [
{
"id": "0acbcc36d9ae2bfb",
"port": 0
}
]
},
{
"x": 1610,
"y": 660,
"wires": [
{
"id": "67eb11bc5a852888",
"port": 0
}
]
},
{
"x": 920,
"y": 360,
"wires": [
{
"id": "7c4703666eaa99fa",
"port": 0
}
]
}
],
"env": [
{
"name": "destUid",
"type": "str",
"value": "",
"ui": {
"label": {
"en-US": "Recipient UID"
},
"type": "input",
"opts": {
"types": [
"str"
]
}
}
},
{
"name": "takMission",
"type": "str",
"value": "",
"ui": {
"label": {
"en-US": "DataSync / TAK Mission"
},
"type": "input",
"opts": {
"types": [
"str"
]
}
}
},
{
"name": "datasyncSave",
"type": "bool",
"value": "false",
"ui": {
"label": {
"en-US": "Save to DataSync"
},
"type": "checkbox"
}
},
{
"name": "creatorUid",
"type": "str",
"value": "",
"ui": {
"label": {
"en-US": "Sender ID"
},
"type": "input",
"opts": {
"types": [
"str"
]
}
}
},
{
"name": "takServerUrl",
"type": "str",
"value": "",
"ui": {
"label": {
"en-US": "TAK Server URL"
},
"type": "input",
"opts": {
"types": [
"str"
]
}
}
},
{
"name": "missionApiPort",
"type": "num",
"value": "8443",
"ui": {
"label": {
"en-US": "TAK Server API Port"
},
"type": "input",
"opts": {
"types": [
"num"
]
}
}
},
{
"name": "tfrStatesList",
"type": "json",
"value": "null",
"ui": {
"label": {
"en-US": "State TFRs"
},
"type": "input",
"opts": {
"types": [
"json"
]
}
}
}
],
"meta": {
"module": "tfr2cot",
"type": "parsrer",
"version": "2.0.0",
"author": "Paul Clifton <paul.clifton@clptak.com>",
"desc": "If msg.payload or env.tfrStatesList is a json-formatted array of 2 letter U.S. abbreviation for a state text strings (e.g. [\"AZ\",\"NC\"]), 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.",
"keywords": "tak,atak,itak,tak-server,tfr,faa,cot",
"license": "Apache-2.0"
},
"color": "#C0DEED",
"inputLabels": [
"msg.paylaod (json)"
],
"outputLabels": [
"msg.payload (json)",
"mission subscription",
"Debug"
],
"icon": "font-awesome/fa-plane",
"flow": [
{
"id": "5249d77ebaebf168",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "Split TFR Array",
"func": "for (var i = 0; i < msg.tfr_list.length; i++) {\n var newMsg = {};\n newMsg.url = msg.tfr_list[i].replace(\"html\",\"xml\");\n newMsg.method = \"GET\"\n node.send(newMsg);\n}\nreturn null;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 220,
"y": 420,
"wires": [
[
"6df4843a1c805046"
]
]
},
{
"id": "6df4843a1c805046",
"type": "http request",
"z": "70eb72484ca97dd5",
"name": "Get TFR xml",
"method": "use",
"ret": "txt",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 400,
"y": 420,
"wires": [
[
"837fc8f45379f72a"
]
]
},
{
"id": "2268bb2949af523c",
"type": "xml",
"z": "70eb72484ca97dd5",
"name": "",
"property": "payload",
"attr": "",
"chr": "",
"x": 790,
"y": 420,
"wires": [
[
"03edc968b374595f"
]
]
},
{
"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;\nconst tfrId = tfr_dict.NotUid[0].txtLocalName[0].replace(/\\//g,\"_\");\n//tfrId = tfrId.replace(/\\//g,\"_\");\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\": \"White\",\n \"role\": \"Team Member\",\n \"phone\": null,\n },\n \"dest\": {\n \"uid\": null,//\"ANDROID-1c2680c542b6c9f6\",\n \"mission\": null,\n \"callsign\": null\n },\n \"link\": {\n \"url\": null,\n \"remarks\": null,\n \"uid\": \"nodered\",\n \"parent_callsign\": \"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 if (tfr_info[i].aseShapes !== undefined) {\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/tfr3/?page=detail_${tfrId}`//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 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 \n //GET COORDINATES & ALTITUDE:\n //[0].Abd[0].Avx[0] !== undefined){\n let kml_coordinates = tfr_info[i].aseShapes[0].Abd[0].Avx[0];\n //if (kml_coordinates !== undefined){\n cot_attrib.lat = parseFloat(kml_coordinates.geoLat[0].replace(\"N\",\"\"));\n cot_attrib.lon = parseFloat(\"-\"+kml_coordinates.geoLong[0].replace(\"W\",\"\"));\n \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 msg.payload = cot_attrib;\n msg.debug = false;\n msg.linkPoints = { \"link\": links };\n return msg;\n} else {\n msg.debug = true;\n msg.debugMessage = \"payload[\\\"XNOTAM - Update\\\"].Group[0].Add[0].Not[0].TfrNot[0].TFRAreaGroup[i].aseShape Does not exist\";\n return msg;\n}};",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [
{
"var": "axios",
"module": "axios"
}
],
"x": 210,
"y": 510,
"wires": [
[
"5443ccddda1cbf80"
]
]
},
{
"id": "8f75d304e5f11f38",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "JSON to PLI CoT ",
"func": "var payload = msg.payload;\nvar uid = payload.uid;\nvar lat = payload.lat;\nvar lon = payload.lon;\nvar altitude = payload.altitude;\n\nvar how = payload.how;\nvar type = payload.type;\nvar detail = payload.detail\nvar stale = \"\";\n\nif (payload.stale){\n stale = payload.stale;\n} else {\n const cinco = 10 * 60 * 1000;\n stale = new Date(Date.now() + cinco).toISOString();\n};\n\nif (uid != null) {\n if (lat != null) {\n if (lon != null) {\n let newpayload = {\n \"event\": {\n \"_attributes\": {\n \"access\":\"UNCLASSIFIED\",\n \"version\": \"2.0\",\n \"uid\": uid,\n \"type\": type,\n \"how\": how,\n \"time\": new Date(Date.now()).toISOString(),\n \"start\": new Date(Date.now()).toISOString(),\n \"stale\": stale,\n },\n \"point\": {\n \"_attributes\": {\n \"lat\": JSON.stringify(lat),\n \"lon\": JSON.stringify(lon),\n \"hae\": \"9999999.0\",\n \"ce\": \"9999999.0\",\n \"le\": \"9999999.0\",\n }\n },\n \"detail\": {\n }\n }\n }\n msg.payload = newpayload;\n msg.cot_detail = detail\n msg.topic = how;\n msg.type = type;\n return msg;\n } else {\n msg.topic = \"unknown\"\n return msg;\n }\n }\n} else {\n msg.topic = \"incomplete\"\n return msg;\n}",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 750,
"y": 510,
"wires": [
[
"fba1b2c9ff2e5ada"
]
],
"inputLabels": [
"msg.payload CoT Attributes"
],
"outputLabels": [
"CoT (JSON-ified)"
],
"info": "# JSON 2 COT - PLI\n\n## JSON INPUT\n```json\nmsg.payload = {\n \"lat\": float,\n \"lon\": float,\n \"altitude\": float,\n \"callsign\": string,\n \"uid\": string,\n \"stale\": time,\n \"groupName\": string,\n \"role\": string,\n \"phone\" string //10 digit with no demarcation\n}\n```\n"
},
{
"id": "fba1b2c9ff2e5ada",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "cot_detail_freeforrm_polygon",
"func": "/*\n Example JSON containing the keys and values for popular cursor on target CoT\nfields, including time, point latitude & longitude, type, and more.\n* /\n\n/* Stale is Date.now() + milliseconds\n Ruberic: 1000 Milliseconds in 1 Second\n Example: 5 minutes, in milliseconds, is 300000\n (5 x 60 * 1000)\n*/\n\nconst cinco = 5 * 60 * 1000;\nconst diez = 2 * cinco;\nvar stale = new Date(Date.now() + diez).toISOString();\n\nconst destination = msg.destination;\nconst detail = msg.cot_detail\nconst cot_base = msg.payload\nvar new_cot = cot_base;\nvar cot_status = [\n {\n \"_attributes\": {\n \"readiness\":\"true\"\n }\n }\n];\nnew_cot.event.detail.status = cot_status;\nvar strokeColor = [\n {\n \"_attributes\": {\n \"value\": \"\"\n }\n }\n];\nnew_cot.event.detail.strokeColor = strokeColor;\nif (detail.shape.strokecolor !== null && detail.shape.strokecolor !== \"\") {\n new_cot.event.detail.strokeColor[0]._attributes.value = detail.shape.strokecolor;\n} else {\n new_cot.event.detail.strokeColor[0]._attributes.value = \"-65536\"\n};\nvar strokeWeight = [\n {\n \"_attributes\": {\n \"value\": \"2.0\"\n }\n }\n ];\nnew_cot.event.detail.strokeWeight = strokeWeight;\nif (detail.shape.strokeweight !== null && detail.shape.strokeweight !== \"\"){\n new_cot.event.detail.strokeWeight[0]._attributes.value = detail.shape.strokeweight;\n} else {\n new_cot.event.detail.strokeWeight[0]._attributes.value = \"2.0\"\n};\nvar fillColor = [\n {\n \"_attributes\": {\n \"value\": \"\"\n }\n }\n];\nnew_cot.event.detail.fillColor = fillColor;\n/*if (detail.shape.fillcolor !== null && detail.shape.fillcolor !== \"\") {\n new_cot.event.detail.fillColor[0]._attributes.value = detail.shape.fillcolor;\n} else {\n new_cot.event.detail.fillColor[0]._attributes.value = \"-65536\"\n};*/\n\nnew_cot.event.detail.fillColor[0]._attributes.value = \"16711680\"\n\n\nvar contact = [\n {\n \"_attributes\": {\n \"callsign\": \"\"\n }\n }\n];\nnew_cot.event.detail.contact = contact;\nif (detail.callsign !== null && detail.callsign !== \"\") {\n new_cot.event.detail.contact[0]._attributes.callsign = detail.callsign;\n} else {\n new_cot.event.detail.contact[0]._attributes.callsign = new_cot.event._attributes.uid;\n};\n\nvar remarks = \"\";\nnew_cot.event.detail.remarks = remarks;\nif (detail.remarks !== null) {\n new_cot.event.detail.remarks = detail.remarks\n};\n \n//var archive= \"\";\n//new_cot.event.detail.archive = archive;\n\nvar labels_on = [\n {\n \"_attributes\": {\n \"value\": \"true\"\n }\n }\n];\nnew_cot.event.detail.labels_on = labels_on;\nif (detail.labels_on !== null && detail.labels_on === \"true\") {\n new_cot.event.detail.labels_on._attributes.value = \"true\"\n};\nvar precisionlocation = [\n {\n \"_attributes\": {\n \"altsrc\": \"???\"\n }\n }\n];\nnew_cot.event.detail.precisionlocation = precisionlocation;\nvar color = [\n {\n \"_attributes\": {\n \"argb\": \"-65536\"\n }\n }\n];\nnew_cot.event.detail.color = color;\nif (detail.shape.color !== null && detail.shape.color !== \"\") {\n new_cot.event.detail.color[0]._attributes.argb = detail.shape.color;\n};\nvar height_attrib = [\n {\n \"_attributes\": {\n \"value\": \"0.0\"\n }\n }\n];\n\nnew_cot.event.detail.height = height_attrib;\nif (detail.height !== null && detail.height !== undefined && detail.height !== \"\") {\n var height = detail.height;\n new_cot.event.detail.height[0]._attributes.value = JSON.stringify(height);\n};\nvar geofence_attrib = [\n {\n \"_attributes\": {\n \"elevationMonitored\": \"true\",\n \"minElevation\": \"0.0\",\n \"monitor\": \"All\",\n \"trigger\": \"Both\",\n \"tracking\": \"false\",\n \"maxElevation\":\"12500\",\n \"boundingSphere\":\"96000.0\"\n }\n }\n];\nnew_cot.event.detail._geofence = geofence_attrib;\nif (height !== undefined && height !== null && height !== \"\"){\n new_cot.event.detail._geofence[0]._attributes.maxElevation = JSON.stringify(height);\n};\n\nmsg.payload = new_cot;\nmsg.cot_detail = detail;\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 990,
"y": 510,
"wires": [
[
"273f997eaf27d6d4"
]
]
},
{
"id": "273f997eaf27d6d4",
"type": "change",
"z": "70eb72484ca97dd5",
"name": "",
"rules": [
{
"t": "set",
"p": "payload.event.detail.link",
"pt": "msg",
"to": "linkPoints.link",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1280,
"y": 510,
"wires": [
[
"11215bd72494711f"
]
]
},
{
"id": "276aa81df27e53c1",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "Add Link URL",
"func": "const detail = msg.cot_detail;\nconst cot_base = msg.payload;\nvar new_cot = cot_base;\n//var links = cot_base.event\nvar link_attrib =[\n {\n \"_attributes\": {\n \"url\": \"\",\n //\"uid\": new_cot.event.uid + \".Style\", // the pass uid must match under event._attribute and \".Style\" to it\n \"type\": \"\",\n \"remarks\": \"\",\n \"relation\": \"r-u\",\n \"mime\": \"text/html\",\n \"version\": \"1.0\"\n }\n }\n];\n\nvar url = false;\n//if (new_cot.detail.link !== null && new_cot.detail.link !== undefined) {\nif (detail.link.url !== undefined){ //&& detail.link.url !== \"\") {\n url = true;\n var linkLength = new_cot.event.detail.link.length;\n new_cot.event.detail.link[linkLength] = link_attrib[0];\n new_cot.event.detail.link[linkLength]._attributes.url = detail.link.url;\n //new_cot.event.detail.link[linkLength][0]._attributes.type = detail.cot_type;\n new_cot.event.detail.link[linkLength]._attributes.remarks = detail.link.remarks;\n new_cot.event.detail.link[linkLength]._attributes.production_time = detail.link.production_time;\n};\n//}\n\nif (url === true) {\n msg.payload = new_cot\n return msg;\n} else {\n msg.payload = cot_base;\n return msg;\n}\n\n//msg.payload = new_cot;\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 580,
"y": 690,
"wires": [
[
"0acbcc36d9ae2bfb"
]
]
},
{
"id": "0acbcc36d9ae2bfb",
"type": "change",
"z": "70eb72484ca97dd5",
"name": "Clean Up",
"rules": [
{
"t": "delete",
"p": "url",
"pt": "msg"
},
{
"t": "delete",
"p": "method",
"pt": "msg"
},
{
"t": "delete",
"p": "statusCode",
"pt": "msg"
},
{
"t": "delete",
"p": "headers",
"pt": "msg"
},
{
"t": "delete",
"p": "responseUrl",
"pt": "msg"
},
{
"t": "delete",
"p": "redirectList",
"pt": "msg"
},
{
"t": "delete",
"p": "retry",
"pt": "msg"
},
{
"t": "delete",
"p": "responseCookies",
"pt": "msg"
},
{
"t": "delete",
"p": "linkPoints",
"pt": "msg"
},
{
"t": "delete",
"p": "type",
"pt": "msg"
},
{
"t": "delete",
"p": "cot_detail",
"pt": "msg"
},
{
"t": "delete",
"p": "topic",
"pt": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 720,
"y": 600,
"wires": [
[
"7ed561833cabfe74"
]
]
},
{
"id": "837fc8f45379f72a",
"type": "switch",
"z": "70eb72484ca97dd5",
"name": "Check https statusCode",
"property": "statusCode",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "200",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 600,
"y": 420,
"wires": [
[
"2268bb2949af523c"
],
[]
]
},
{
"id": "e614f91fceb0d546",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "Add Marti (recipient)",
"func": "//const payload = msg.payload\nvar destination = msg.cot_detail.dest;\nlet datasyncSave = env.get(\"datasyncSave\");\nlet defaultUid = env.get(\"destUid\");\nif (destination.uid === null /*&& destination.uid === \"\" && destination.uid === undefined*/) {\n if (defaultUid !== \"\" /*&& defaultUid !== null && defaultUid !== undefined */) {\n destination.uid = defaultUid;\n } else {\n destination.uid = null;\n }\n} else {\n destination.uid = null;\n};\n\nlet defaultTakMission = env.get(\"takMission\");\nlet defaultCreatorUid = env.get(\"creatorUid\")\nif (destination.mission === null ) {\n if (defaultTakMission !== \"\" ) {\n destination.mission = defaultTakMission;\n if (defaultCreatorUid !== \"\") {\n destination.creatorUid = defaultCreatorUid;\n } else {\n destination.creatorUid = null\n }\n } else {\n destination.mission = null;\n }\n} else {\n destination.mission = null;\n};\n\nvar destInfo = {\n \"recipientUid\": destination.uid,\n \"takMission\": destination.mission,\n \"creatorUid\": destination.creatorUid,\n \"cotUid\": msg.payload.event._attributes.uid,\n \"datasyncSave\": datasyncSave\n};\n//msg.destination = destInfo;\nconst cot_base = msg.payload;\nvar new_cot = cot_base;\n\nvar marti = //{\"marti\":\n [\n {\n \"dest\": {\n \"_attributes\": {\n }\n }\n }\n ]\n\nif (new_cot.event.detail.marti !== null) {\n new_cot.event.detail.marti = marti;\n //msg.payload = new_cot.event.detail.marti = marti;\n //return msg;\n}\nif (destination.mission !== null && destination.mission !== \"\") {\n var mission = true;\n new_cot.event.detail.marti[0].dest._attributes.mission = destination.mission;\n }\nif (destination.uid !== null && destination.uid !== \"\") {\n var uid = true;\n// marti.marti[0].dest._attributes.uid = destination.uid;\n new_cot.event.detail.marti[0].dest._attributes.uid = destination.uid;\n} else {\n //new_cot.event.detail.marti[0].dest._attributes.uid = null;//\"ANDROID-1c2680c542b6c9f6\";\n};\nif (destination.callsign !== null && destination.callsign !== \"\") {\n var callsign = true\n// marti.marti[0].dest._attributes.callsign = destination.callsign;\n new_cot.event.detail.marti[0].dest._attributes.callsign = destination.callsign;\n};\nif (mission === true) {\n msg.payload = new_cot\n msg.destination = destInfo;\n return msg;\n} else if (uid === true){\n msg.payload = new_cot;\n msg.destination = destInfo;\n return msg;\n} else if (callsign === true) {\n msg.payload = new_cot;\n msg.destination = destInfo;\n return msg;\n} else {\n msg.payload = cot_base;\n msg.destination = destInfo;\n return msg;\n }",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 490,
"y": 600,
"wires": [
[
"276aa81df27e53c1"
]
]
},
{
"id": "df8b6778d5ff8bfe",
"type": "switch",
"z": "70eb72484ca97dd5",
"name": "",
"property": "datasync",
"propertyType": "msg",
"rules": [
{
"t": "false"
},
{
"t": "true"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 1100,
"y": 600,
"wires": [
[],
[
"0f0b501e9c9772f0"
]
]
},
{
"id": "67eb11bc5a852888",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "Post Sent CoT to Mission",
"func": "const payload = msg.destination;\n//const creatorUid = payload.creatorUid;\nconst cotUid = payload.cotUid;\nconst takMission = payload.takMission;\nlet creatorUid = env.get(\"creatorUid\");\nlet takServerUrl = env.get(\"takServerUrl\");\nlet missionApiPort = env.get(\"missionApiPort\");\nvar data = {\"uids\":[cotUid]};\n//if (takMission !== \"\" && creatorUid !== \"\" && takServerUrl !== \"\" && missionApiPort !== \"\") {\n msg.url = msg.url = \"https://\" + takServerUrl + \":\" + missionApiPort.toString() + \"/Marti/api/missions/\" + takMission + '/contents?creatorUid=' + creatorUid; \n msg.header = {\n \"accept\": \"*/*\",\n \"Content-Type\": \"application/json\"\n };\n msg.method = \"PUT\";\n msg.payload = {\"uids\": [\n cotUid\n ]\n };\n return msg;\n// };\n//return msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1630,
"y": 600,
"wires": [
[]
]
},
{
"id": "7ed561833cabfe74",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "Check Save to DataSync",
"func": "let datasync = env.get(\"datasyncSave\");\nmsg.datasync = datasync;\nconst payload = msg.destination;\nmsg.destination = payload;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 920,
"y": 600,
"wires": [
[
"df8b6778d5ff8bfe"
]
]
},
{
"id": "11215bd72494711f",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "Check Save to DataSync",
"func": "let datasync = env.get(\"datasyncSave\");\nmsg.datasync = datasync;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1570,
"y": 510,
"wires": [
[
"f926636b19eebca4"
]
]
},
{
"id": "f926636b19eebca4",
"type": "switch",
"z": "70eb72484ca97dd5",
"name": "Check DataSync Save Status",
"property": "datasync",
"propertyType": "msg",
"rules": [
{
"t": "true"
},
{
"t": "false"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 230,
"y": 600,
"wires": [
[
"e614f91fceb0d546"
],
[
"276aa81df27e53c1"
]
]
},
{
"id": "0f0b501e9c9772f0",
"type": "function",
"z": "70eb72484ca97dd5",
"name": "Check Destination",
"func": "let destination = msg.destination;\nif (destination !== undefined) {\n msg.topic = true\n} else (\n msg.topic = false\n)\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 600,
"wires": [
[
"22e0e43169d529a0"
]
]
},
{
"id": "22e0e43169d529a0",
"type": "switch",
"z": "70eb72484ca97dd5",
"name": "",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "true"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 1430,
"y": 600,
"wires": [
[
"67eb11bc5a852888"
]
]
},
{
"id": "5443ccddda1cbf80",
"type": "switch",
"z": "70eb72484ca97dd5",
"name": "Check Bugs",
"property": "debug",
"propertyType": "msg",
"rules": [
{
"t": "false"
},
{
"t": "true"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 440,
"y": 510,
"wires": [
[
"8f75d304e5f11f38"
],
[]
]
},
{
"id": "9a2ebce9d96d8425",
"type": "http request",
"z": "70eb72484ca97dd5",
"name": "",