From 942186035dfe51c960d87578d1d1888f9c218d73 Mon Sep 17 00:00:00 2001 From: Dave Conway-Jones Date: Fri, 11 Aug 2023 15:21:34 +0100 Subject: [PATCH] Add TAK input capability --- CHANGELOG.md | 1 + README.md | 13 +++++++-- package.json | 5 ++-- worldmap.html | 4 +-- worldmap/worldmap.js | 69 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 85 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1205406..d92fe7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### Change Log for Node-RED Worldmap + - v2.40.0 - Add handling for TAK event points from TAK ingest node. - v2.39.0 - Add client timezone to connect message. PR #245 - v2.38.3 - Better fix for geojson multipoint icons. - v2.38.1 - Fix for geojson multipoint icons. diff --git a/README.md b/README.md index 38160e9..4021ea0 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Feel free to [![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D% ### Updates +- v2.40.0 - Add handling for TAK event points from TAK ingest node. - v2.39.0 - Add client timezone to connect message. PR #245 - v2.38.3 - Better fix for geojson multipoint icons. - v2.38.1 - Fix for geojson multipoint icons. @@ -118,10 +119,18 @@ To do this you need to supply a `msg.payload.SIDC` 2525 code instead of an icon, "options": { "fillOpacity":0.8, "additionalInformation":"Extra info" } } -SIDC codes can be generated using the online tool - https://spatialillusions.com/unitgenerator/ +SIDC codes can be generated using the online tool - https://www.spatialillusions.com/unitgenerator-legacy/ There are lots of extra options you can specify as `msg.payload.options` - see the milsymbol docs here. +#### TAK Visualisation + +Users of [TAK](https://tak.gov) can use the [TAK ingest node](https://flows.nodered.org/node/node-red-contrib-tak-registration) to create a JSON formatted TAK event object, received from a TAK server. This can be fed directly into the worldmap node. + +![Tak Flow](https://github.com/dceejay/pages/blob/master/TAKflow.png?raw=true) +![Tak Image](https://github.com/dceejay/pages/blob/master/TAKicons.png?raw=true) + + ### Areas, Rectangles, Lines, and GreatCircles If the msg.payload contains an **area** property - that is an array of co-ordinates, e.g. @@ -698,7 +707,7 @@ and use a url like `"url": "http://localhost:1882/?map=/maps/my-app.map",` To use a vector mbtiles server like **MapTiler** then you can download your mbtiles file into a directory and then from that directory run ``` -docker run --name maptiler -d -v $(pwd):/data -p 1884:8080 maptiler/tileserver-gl -p 8080 +docker run --name maptiler -d -v $(pwd):/data -p 1884:8080 maptiler/tileserver-gl -p 8080 --mbtiles yourMapFile.mbtiles ``` and use a url like `"url": "http://localhost:1884/styles/basic-preview/{z}/{x}/{y}.png"` diff --git a/package.json b/package.json index 44db8c0..7e9556a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-web-worldmap", - "version": "2.39.0", + "version": "2.40.0", "description": "A Node-RED node to provide a web page of a world map for plotting things on.", "dependencies": { "@turf/bezier-spline": "~6.5.0", @@ -24,7 +24,8 @@ "keywords": [ "node-red", "map", - "world" + "world", + "tak" ], "node-red": { "version": ">=1.0.0", diff --git a/worldmap.html b/worldmap.html index 0f8f51c..6b69db6 100644 --- a/worldmap.html +++ b/worldmap.html @@ -146,7 +146,7 @@ If Web Path is left empty, then by default ⌘⇧m - c

Icons of type plane, ship, car, uav or arrow will use built in SVG icons that align to the bearing value.

Font Awesome (fa-icons 4.7) can also be used, as can - NATO symbology codes (SIDC), or :emoji name:, + NATO symbology codes (SIDC), or :emoji name:, or the url of a small icon image (32x32)

See the README for further details and examples of icons and commands for drawing lines and areas, and to add layers and @@ -312,7 +312,7 @@ If Web Path is left empty, then by default ⌘⇧m - c

Icons of type plane, ship, car, uav or arrow will use built in SVG icons that align to the bearing value.

Font Awesome (fa-icons 4.7) can also be used, as can - NATO symbology codes (SIDC), or :emoji name:, + NATO symbology codes (SIDC), or :emoji name:, or the url of a small icon image (32x32)

See the README for further details and examples of icons and commands for drawing lines and areas, and to add layers and diff --git a/worldmap/worldmap.js b/worldmap/worldmap.js index 1f00678..22316ef 100644 --- a/worldmap/worldmap.js +++ b/worldmap/worldmap.js @@ -18,7 +18,7 @@ var menuOpen = false; var clusterAt = 0; var maxage = 900; // default max age of icons on map in seconds - cleared after 10 mins var baselayername = "OSM grey"; // Default base layer OSM but uniform grey -var pagefoot = " © DCJ 2022" +var pagefoot = " © DCJ 2023" var inIframe = false; var showUserMenu = true; var showLayerMenu = true; @@ -117,12 +117,23 @@ var handleData = function(data) { } } if (data.command) { doCommand(data.command); delete data.command; } + + // handle raw geojson type msg if (data.hasOwnProperty("type") && data.type.indexOf("Feature") === 0) { if (data.hasOwnProperty('properties') && data.properties.hasOwnProperty('title')) { doGeojson(data.properties.title,data) } else { doGeojson("geojson",data); } } + // handle TAK json (from tak-ingest node or fastxml node) + else if (data.hasOwnProperty("event") && data.event.hasOwnProperty("point")) { + doTAKjson(data.event); + } + // handle TAK json (from multicast Protobuf) + else if (data.hasOwnProperty("cotEvent") && data.cotEvent.hasOwnProperty("lat") && data.cotEvent.hasOwnProperty("lon")) { + doTAKMCjson(data.cotEvent); + } + // handle default worldmap json msg else if (data.hasOwnProperty("name")) { setMarker(data); } else { if (JSON.stringify(data) !== '{}') { @@ -2910,3 +2921,59 @@ function doGeojson(n,g,l,o) { layers[lay].addLayer(markers[n]); map.addLayer(layers[lay]); } + +// handle TAK messages from TAK server tcp - XML->JSON +function doTAKjson(p) { + // console.log("TAK event",p); + if (p.type.indexOf('a') === 0) { + var d = {}; + d.lat = Number(p.point.lat); + d.lon = Number(p.point.lon); + d.group = p.detail?.__group?.name; + d.role = p.detail?.__group?.role; + d.type = p.type; + d.uid = p.uid; + d.name = p.detail?.contact?.callsign || p.uid; + d.hdg = p.detail?.track?.course; + d.speed = p.detail?.track?.speed; + var i = d.type.split('-').join('').toUpperCase(); + if (i[0] === 'A') { i = 'S' + i.substr(1,2) + 'P' + i.substr(3); } + d.SIDC = (i + '------------').substr(0,12); + d.timestamp = Date.parse(p.time); + d.ttl = Date.parse(p.stale); + // d.now = Date.now(); + d.alt = Number(p.point.hae) || 9999999; + setMarker(d); + } + else { + console.log("Skip TAK type",p.type); + } +} + +// handle TAK messages from TAK Multicast - Protobuf->JSON +function doTAKMCjson(p) { + // console.log("TAK Multicast event",p); + if (p.type.indexOf('a') === 0) { + var d = {}; + d.lat = p.lat; + d.lon = p.lon; + d.group = p.detail?.group?.name; + d.role = p.detail?.group?.role; + d.type = p.type; + d.uid = p.uid; + d.name = p.detail?.contact?.callsign || p.uid; + d.hdg = p.detail?.track?.course; + d.speed = p.detail?.track?.speed; + var i = d.type.split('-').join('').toUpperCase(); + if (i[0] === 'A') { i = 'S' + i.substr(1,2) + 'P' + i.substr(3); } + d.SIDC = (i + '------------').substr(0,12); + d.timestamp = Number(p.sendTime); + d.ttl = Number(p.staleTime); + // d.now = Date.now(); + d.alt = p.hae || 9999999; + setMarker(d); + } + else { + console.log("Skip TAK type",p.type); + } +} \ No newline at end of file