From 0b86ecefa5356995799fda790700ac32086f3c6a Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Mon, 25 Sep 2017 15:28:52 -0700 Subject: [PATCH] Added different location support to map --- mesherrors.txt | 57 ++++++++++ package.json | 2 +- public/images/mapmarker-gps.png | Bin 0 -> 1587 bytes public/images/mapmarker-ip.png | Bin 0 -> 1480 bytes public/images/mapmarker-user.png | Bin 0 -> 1547 bytes public/images/mapmarker-wifi.png | Bin 0 -> 1616 bytes public/styles/ol3-contextmenu.min.css | 7 ++ views/default.handlebars | 144 +++++++++++++++++--------- webserver.js | 14 ++- 9 files changed, 175 insertions(+), 49 deletions(-) create mode 100644 public/images/mapmarker-gps.png create mode 100644 public/images/mapmarker-ip.png create mode 100644 public/images/mapmarker-user.png create mode 100644 public/images/mapmarker-wifi.png create mode 100644 public/styles/ol3-contextmenu.min.css diff --git a/mesherrors.txt b/mesherrors.txt index fca6f59f..dc8b3a85 100644 --- a/mesherrors.txt +++ b/mesherrors.txt @@ -50,3 +50,60 @@ TypeError: socket.getPeerCertificate is not a function at TCP.onconnection (net.js:1452:8) +-------- 9/25/2017, 1:57:36 PM -------- + +C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1589 + if ((node.userloc) && (node.userloc.length != 2)) return; + ^ + +ReferenceError: node is not defined + at WebSocket. (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1589:34) + at emitTwo (events.js:106:13) + at WebSocket.emit (events.js:191:7) + at Receiver.ontext (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\ws\lib\WebSocket.js:841:10) + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\ws\lib\Receiver.js:536:18 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\ws\lib\Receiver.js:368:7 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\ws\lib\PerMessageDeflate.js:249:5 + at afterWrite (_stream_writable.js:360:3) + at onwrite (_stream_writable.js:351:7) + at WritableState.onwrite (_stream_writable.js:89:5) + + +-------- 9/25/2017, 2:01:16 PM -------- + +C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1616 + command.userloc.push((Math.floor((new Date(iploc.date)) / 1000))); + ^ + +ReferenceError: iploc is not defined + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1616:88 + at newArguments.(anonymous function) (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\executor.js:29:17) + at Cursor.execFn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:484:12) + at callback (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:126:19) + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:193:12 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:329:14 + at Object.async.eachSeries (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:130:20) + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:323:11 + at fn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:582:34) + at Immediate._onImmediate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:498:34) + + +-------- 9/25/2017, 2:02:08 PM -------- + +C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1617 + node.userloc = command.join(','); + ^ + +TypeError: command.join is not a function + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1617:68 + at newArguments.(anonymous function) (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\executor.js:29:17) + at Cursor.execFn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:484:12) + at callback (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:126:19) + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:193:12 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:329:14 + at Object.async.eachSeries (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:130:20) + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:323:11 + at fn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:582:34) + at Immediate._onImmediate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:498:34) + + diff --git a/package.json b/package.json index 8106d5c4..1a109cec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.0.8-d", + "version": "0.0.8-e", "keywords": [ "Remote Management", "Intel AMT", diff --git a/public/images/mapmarker-gps.png b/public/images/mapmarker-gps.png new file mode 100644 index 0000000000000000000000000000000000000000..5b047bf4e25c79de2ecacf4a978a7f902d0a9905 GIT binary patch literal 1587 zcmV-32F&@1P)004R=004l4008;_004mL004C`008P>0026e000+nl3&F}00009 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 O0000 + @@ -21,6 +22,7 @@ + MeshCentral @@ -1003,6 +1005,9 @@ node.desc = message.event.node.desc; node.publicip = message.event.node.publicip; node.iploc = message.event.node.iploc; + node.wifiloc = message.event.node.wifiloc; + node.gpsloc = message.event.node.gpsloc; + node.userloc = message.event.node.userloc; if (message.event.node.agent != undefined) { if (node.agent == undefined) node.agent = {}; if (message.event.node.agent.ver != undefined) { node.agent.ver = message.event.node.agent.ver; } @@ -1027,6 +1032,8 @@ drawNotifications(); refreshDevice(node._id); updateMapMarkers(); + + if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); } } break; } @@ -1673,16 +1680,15 @@ var boundingBox = null; for (var i in nodes) { var loc = map_parseNodeLoc(nodes[i]); - if (loc) { // Draw markers for devices with locations + var feature = xxmap.markersSource.getFeatureById(nodes[i]._id); // Remove if present + if ((loc != null) && ((nodes[i].meshid == selectedMesh) || (selectedMesh == undefined))) { // Draw markers for devices with locations lat = loc[0]; lon = loc[1]; + var type = loc[2]; if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } } - var feature = xxmap.markersSource.getFeatureById(nodes[i]._id); - if (nodes[i].meshid == selectedMesh || selectedMesh == undefined) { - if (feature == null || feature == undefined) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); } // Update Feature - } else { - if (feature) { xxmap.markersSource.removeFeature(feature); } // Remove if it does not belong to that mesh - } + if (feature == null) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); feature.setStyle(markerStyle(nodes[i], loc[2])); } // Update Feature + } else { + if (feature) { xxmap.markersSource.removeFeature(feature); } } } return boundingBox; @@ -1692,10 +1698,15 @@ var map_cm_popup = new ol.Overlay({ element: Q('xmap-info-window'), positioning: 'bottom-center', stopEvent: false }); // Edit Marker item - var map_cm_editMarker = { text: "Modify Node location", callback: function (obj) { modifyMarkerloc(obj.data); } }; + var map_cm_editMarker = { text: "Modify node location", callback: function (obj) { modifyMarkerloc(obj.data); } }; + + // Clear Marker item + var map_cm_clearMarker = { text: "Remove node location", callback: function (obj) { + meshserver.Send({ action: 'changedevice', nodeid: obj.data.a, userloc: [] }); // Clear the user position marker + }}; // Save Marker item - var map_cm_saveMarker = { text: "Save Node location", callback: function (obj) { saveMarkerloc(obj.data); } }; + var map_cm_saveMarker = { text: "Save node location", callback: function (obj) { saveMarkerloc(obj.data); } }; // Build a context menu for a feature var map_cm_nodemenu_items = [ @@ -1724,9 +1735,14 @@ // Get the lat/lon from a node function map_parseNodeLoc(node) { - if (!node.iploc) return; - var loc = node.iploc.split(','); - return [parseFloat(loc[0]) + (stringToIntHash(node._id.substring(0, 20)) / 100000000000), parseFloat(loc[1]) + (stringToIntHash(node._id.substring(20)) / 100000000000)] + var loc = null, t = 0; + if (node.iploc) { loc = node.iploc; t = 1; } + if (node.wifiloc) { loc = node.wifiloc; t = 2; } + if (node.gpsloc) { loc = node.gpsloc; t = 3; } + if (node.userloc) { loc = node.userloc; t = 4; } + if ((loc == null) || (typeof loc != 'string')) return; + loc = loc.split(','); + return [ parseFloat(loc[0]) + (stringToIntHash(node._id.substring(0, 20)) / 100000000000), parseFloat(loc[1]) + (stringToIntHash(node._id.substring(20)) / 100000000000), t ] } // Load the entire map @@ -1792,7 +1808,6 @@ } }); - /* // Initialize context menu for openlayers contextmenu = new ContextMenu({ width: 160, @@ -1805,20 +1820,18 @@ var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(ft, l){ return ft; }); xxmap.contextmenu.clear(); //Clear the context menu if (feature) { - var featId=feature.getId(); - if (featId) { // Node feature will have an id - addContextMenuItems(feature); - } + var featId = feature.getId(); + if (featId) { addContextMenuItems(feature); } // Node feature will have an id else { // If the feature is a pointer, Get its corresponding Node feature - var nodeFeature= getCorrespondingFeature(feature); //return the node feature associated to pointer. + var nodeFeature = getCorrespondingFeature(feature); //return the node feature associated to pointer. if (nodeFeature) { addContextMenuItems(nodeFeature); } else{ xxmap.contextmenu.extend(contextmenu_items); } } } else { xxmap.contextmenu.extend(contextmenu_items); } }); + if (xxmap.contextmenu == null) { xxmap.contextmenu = contextmenu; } xxmap.map.addControl(xxmap.contextmenu); - */ //addMeshOptions(); // Adds Mesh names to mesh dropdown } catch (e) { QV('viewselectmapoption', false); @@ -1827,24 +1840,24 @@ } // Add feature on to Map for a Node - function addFeature(node, lat, lon){ + function addFeature(node, lat, lon) { var existingfeature = getModifiedFeature(node._id); // Check if Corresponding feature was Modified ( Modifed feature are in active interactions list) if (existingfeature) { xxmap.markersSource.addFeature(existingfeature); } // Add that existing feature else { // Add new feature for this node if (!lat && !lon) { var loc = map_parseNodeLoc(node); lat = loc[0]; lon = loc[1]; } - var feature = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform([lon, lat], 'EPSG:4326','EPSG:3857')), name: node.name, status: node.conn, lat: lat, lon: lon }); - feature.setId(node._id); // Set id for the device as nodeid - feature.setStyle(markerStyle(node)); - xxmap.markersSource.addFeature(feature); // Add the feature to Marker Source + if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon + var feature = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform([lon, lat], 'EPSG:4326','EPSG:3857')), name: node.name, status: node.conn, lat: lat, lon: lon }); + feature.setId(node._id); // Set id for the device as nodeid + feature.setStyle(markerStyle(node)); + xxmap.markersSource.addFeature(feature); // Add the feature to Marker Source + } } } // Removing any feature from map function removeFeature(node) { - if (node.iploc) { - var feature = xxmap.markersSource.getFeatureById(node._id); - if (feature) { xxmap.markersSource.removeFeature(feature); } - } + var feature = xxmap.markersSource.getFeatureById(node._id); + if (feature) { xxmap.markersSource.removeFeature(feature); } } // Update feature @@ -1870,6 +1883,7 @@ function modifyMarkerloc(ft){ var featid = ft.getId(); if (featid) { + ft.setStyle(markerStyle(getNodeFromId(ft.a), 4)); // Switch to a user marker if ( !getActiveInteractions(ft)) { var dragInteration = new ol.interaction.Modify({ features: new ol.Collection([ft]), @@ -1891,16 +1905,25 @@ removeInteraction(featid); var coord = ft.getGeometry().getCoordinates(); var v = ol.proj.transform(coord, 'EPSG:3857', 'EPSG:4326'); - meshserver.Send({ action: 'changelocation', nodeid: featid, value: v }); // Send them to server to save changes + var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long + meshserver.Send({ action: 'changedevice', nodeid: featid, userloc: vx }); // Send them to server to save changes } } } // Style the Markers - function markerStyle(node) { + function markerStyle(node, type) { + if (type == null) { + type = 0; + if (node.iploc) { type = 1; } + if (node.wifiloc) { type = 2; } + if (node.gpsloc) { type = 3; } + if (node.userloc) { type = 4; } + } + var types = ['', '-ip','-wifi','-gps','-user']; var color = connStateColor(node); var style = new ol.style.Style({ - image: new ol.style.Icon({ color: color, anchor: [0.5, 1], src: 'images/mapmarker.png' }) + image: new ol.style.Icon({ color: color, anchor: [0.5, 1], src: 'images/mapmarker' + types[type] + '.png' }) //stroke: new ol.style.Stroke({ color: '#000', width: 20 }) //text: new ol.style.Text({ text: 'bob!', textAlign: 'right', offsetX: -10, fill: new ol.style.Fill({ color: '#000' }), stroke: new ol.style.Stroke({ color: '#fff', width: 2 }) }) }); @@ -1935,6 +1958,11 @@ } else { map_cm_editMarker.data = feature; xxmap.contextmenu.push(map_cm_editMarker); + var node = getNodeFromId(feature.a); + if (node.userloc) { + map_cm_clearMarker.data = feature; + xxmap.contextmenu.push(map_cm_clearMarker); + } } map_cm_nodemenu_items.forEach(function (item){ if (item.text == 'Zoom-in to extent' || item.text == 'Zoom-out to extent') { item.data = feature; } @@ -2047,6 +2075,7 @@ if (node) { var feature = markersSource.getFeatureById(i); var v = ol.proj.transform(coords, 'EPSG:3857', 'EPSG:4326'); + var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long if (button == 2) { if (feature) { feature.getGeometry().setCoordinates(coords); @@ -2054,10 +2083,10 @@ if (activeInteraction) { saveMarkerloc(feature); } else { // If this feature is not modified, then send updated coords to server. - meshserver.Send({ action: 'changelocation', nodeid: node._id, value: v }); // Send them to server to save changes + meshserver.Send({ action: 'changedevice', nodeid: node._id, value: vx }); // Send them to server to save changes } } else { - meshserver.Send({ action: 'changelocation', nodeid: node._id, value: v }); // This Node is not yet added to maps. + meshserver.Send({ action: 'changedevice', nodeid: node._id, value: vx }); // This Node is not yet added to maps. } } else if (button == 1) { @@ -2065,11 +2094,11 @@ feature.getGeometry().setCoordinates(coords); modifyMarkerloc(feature); } else { - if (!node.iploc) { + //if (map_parseNodeLoc(node.iploc) != null) { addFeature(node, v[0], v[1]); var newFeature = markersSource.getFeatureById(node._id); modifyMarkerloc(newFeature); - } + //} } } } @@ -2438,7 +2467,7 @@ if ((meshrights & 4) != 0) x += 'Delete Device'; x += '
'; if (mesh.mtype == 2) x += 'Interfaces '; - if ((node.iploc) && (xxmap != null)) x += 'Location '; + if (xxmap != null) x += 'Location '; x += '

' QH('p10html3', x); @@ -2650,26 +2679,47 @@ // Show current location var d2map = null; function p10showNodeLocationDialog() { - if (xxdialogMode) return; - var loc = currentNode.iploc.split(','); - var lat = parseFloat(loc[0]); - var lng = parseFloat(loc[1]); - //var x = ''; - var x = '
'; - setDialogMode(2, "Device Location", 1, null, x); + if ((xxdialogMode != null) && (xxdialogTag == '@xxmap')) { setDialogMode(0); } else { if (xxdialogMode) return; } + var markers = [], types = ['iploc', 'wifiloc', 'gpsloc', 'userloc'], boundingBox = null; + + for (var loctype in types) { + if (currentNode[types[loctype]] != null) { + var loc = currentNode[types[loctype]].split(','), lat = parseFloat(loc[0]), lon = parseFloat(loc[1]); + if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon + var deviceMark = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.fromLonLat([lon, lat])) }); + deviceMark.setStyle(markerStyle(currentNode, parseInt(loctype) + 1)); + markers.push(deviceMark); + + if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } } + } + } + } // Setup the device mark layer - var deviceMark = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.fromLonLat([lng, lat])) }); - deviceMark.setStyle(markerStyle(currentNode)); - var vectorSource = new ol.source.Vector({ features: [deviceMark] }); + var vectorSource = new ol.source.Vector({ features: markers }); var vectorLayer = new ol.layer.Vector({ source: vectorSource }); + //var x = ''; + var x = '
'; + setDialogMode(2, "Device Location", 1, null, x, '@xxmap'); + + var clng = 0, clat = 0, zoom = 8; + if (boundingBox != null) { + var clat = (boundingBox[0] + boundingBox[2]) / 2; + var clng = (boundingBox[1] + boundingBox[3]) / 2; + var cscale = Math.max(Math.abs(boundingBox[0] - boundingBox[2]), Math.abs(boundingBox[1] - boundingBox[3])); + var i = 360, zoom = -2; + while (i > cscale) { zoom++; i = i / 2; } + } + + if (markers.length == 1) { zoom = 8; } + // Setup the map d2map = new ol.Map({ target: 'd2map', interactions: ol.interaction.defaults({dragPan:false, mouseWheelZoom:false}), layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer ], - view: new ol.View({ center: ol.proj.fromLonLat([lng, lat]), zoom: 8 }) + view: new ol.View({ center: ol.proj.fromLonLat([clng, clat]), zoom: zoom }) }); } diff --git a/webserver.js b/webserver.js index 4718f8b1..e1297f7b 100644 --- a/webserver.js +++ b/webserver.js @@ -1586,7 +1586,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate { // Argument validation if ((command.nodeid == null) || (typeof command.nodeid != 'string') || (command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain - + if ((command.userloc) && (command.userloc.length != 2) && (command.userloc.length != 0)) return; + // Change the device obj.db.Get(command.nodeid, function (err, nodes) { if (nodes.length != 1) return; @@ -1606,6 +1607,17 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate if (command.icon && (command.icon != node.icon)) { change = 1; node.icon = command.icon; changes.push('icon'); } if (command.name && (command.name != node.name)) { change = 1; node.name = command.name; changes.push('name'); } if (command.host && (command.host != node.host)) { change = 1; node.host = command.host; changes.push('host'); } + if (command.userloc && ((node.userloc == null) || (command.userloc[0] != node.userloc[0]) || (command.userloc[1] != node.userloc[1]))) { + change = 1; + if ((command.userloc.length == 0) && (node.userloc)) { + delete node.userloc; + changes.push('location removed'); + } else { + command.userloc.push((Math.floor((new Date()) / 1000))); + node.userloc = command.userloc.join(','); + changes.push('location'); + } + } if (command.desc != null && (command.desc != node.desc)) { change = 1; node.desc = command.desc; changes.push('description'); } if (command.intelamt != null) { if ((command.intelamt.user != null) && (command.intelamt.pass != undefined) && ((command.intelamt.user != node.intelamt.user) || (command.intelamt.pass != node.intelamt.pass))) { change = 1; node.intelamt.user = command.intelamt.user; node.intelamt.pass = command.intelamt.pass; changes.push('Intel AMT credentials'); }