forked from community/device-mgt-core
parent
f4af47fae4
commit
dcac19480f
@ -1,20 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2013 Masayuki Tanaka
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,26 +0,0 @@
|
|||||||
Copyright (c) 2010-2014, Michael Bostock
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* The name Michael Bostock may not be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
|
|
||||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
||||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,8 +0,0 @@
|
|||||||
$(function() {
|
|
||||||
$("#timeFromCal").datepicker({
|
|
||||||
orientation: 'top'
|
|
||||||
});
|
|
||||||
$("#timeToCal").datepicker({
|
|
||||||
orientation: 'top'
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var centerLocation = new L.LatLng(6.999833130825296, 79.99855044297874);
|
|
||||||
var resizeIconLocation = new L.LatLng(6.99847, 80.14412);
|
|
||||||
var proximityMap = L.map("proximityMap", {
|
|
||||||
zoom: 10,
|
|
||||||
center: centerLocation,
|
|
||||||
zoomControl: false,
|
|
||||||
attributionControl: false,
|
|
||||||
maxZoom: 20
|
|
||||||
});
|
|
||||||
var proximityDistance = $("#proximityDistance");
|
|
||||||
//TODO invoker-util
|
|
||||||
var serverUrl = "/api/device-mgt/v1.0/geo-services/alerts/Proximity/" + deviceType + "/" + deviceId;
|
|
||||||
// var serverUrl = "/portal/store/carbon.super/fs/gadget/geo-dashboard/controllers/get_alerts.jag?executionPlanType=Proximity&deviceId=" + deviceId;
|
|
||||||
invokerUtil.get(serverUrl, function (response) {
|
|
||||||
response = JSON.parse(response);
|
|
||||||
proximityDistance.val(response.proximityDistance);
|
|
||||||
$("#proximityTime").val(response.proximityTime);
|
|
||||||
});
|
|
||||||
|
|
||||||
L.grid({
|
|
||||||
redraw: 'move'
|
|
||||||
}).addTo(proximityMap);
|
|
||||||
|
|
||||||
proximityMap.scrollWheelZoom.disable();
|
|
||||||
|
|
||||||
var marker = L.marker(centerLocation).setIcon(normalMovingIcon);
|
|
||||||
|
|
||||||
marker.addTo(proximityMap);
|
|
||||||
|
|
||||||
var resizeIcon = L.icon({
|
|
||||||
iconUrl: ApplicationOptions.leaflet.iconUrls.resizeIcon,
|
|
||||||
iconAnchor: [24, 24]
|
|
||||||
});
|
|
||||||
|
|
||||||
var resizeMarker = L.marker(resizeIconLocation, {icon: resizeIcon, draggable: 'true'}).addTo(proximityMap);
|
|
||||||
resizeMarker.on('drag', updateRuler);
|
|
||||||
|
|
||||||
var measureLine = new L.Polyline(
|
|
||||||
[centerLocation, resizeIconLocation ],
|
|
||||||
{ color: "black", opacity: 0.5, stroke: true });
|
|
||||||
|
|
||||||
|
|
||||||
proximityMap.addLayer(measureLine);
|
|
||||||
measureLine._path.setAttribute("class", 'measuring-line-for-look');
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
minWidth: 50,
|
|
||||||
autoPan: false,
|
|
||||||
closeButton: true, // should the popups have a close option?
|
|
||||||
displayTotalDistance: true,
|
|
||||||
displayPartialDistance: false,
|
|
||||||
className: 'measuring-label-tooltip' /*css label class name*/
|
|
||||||
};
|
|
||||||
// var totalDistancePopup = new L.Popup(options,measureLine);
|
|
||||||
var initialDistance = centerLocation.distanceTo(resizeIconLocation);
|
|
||||||
|
|
||||||
var measureCircle = L.circle(centerLocation, initialDistance).addTo(proximityMap);
|
|
||||||
|
|
||||||
function updateRuler(e) {
|
|
||||||
var target = e.target;
|
|
||||||
resizeIconLocation = target.getLatLng();
|
|
||||||
measureLine.setLatLngs([centerLocation, resizeIconLocation]);
|
|
||||||
setDistancePopup(centerLocation, resizeIconLocation)
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDistancePopup(startLatLng, endLatLng) {
|
|
||||||
var centerPos = new L.LatLng((startLatLng.lat + endLatLng.lat) / 2,
|
|
||||||
(startLatLng.lng + endLatLng.lng) / 2),
|
|
||||||
distance = startLatLng.distanceTo(endLatLng);
|
|
||||||
proximityDistance.val(distance.toFixed(2));
|
|
||||||
measureCircle.setRadius(distance);
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function setSpeed() {
|
|
||||||
var serverUrl = "/api/device-mgt/v1.0/geo-services/alerts/Speed/" + deviceType + "/" + deviceId;
|
|
||||||
// var serverUrl = "/portal/store/carbon.super/fs/gadget/geo-dashboard/controllers/get_alerts.jag?executionPlanType=Speed&deviceId=" + deviceId;
|
|
||||||
invokerUtil.get(serverUrl, function (response) {
|
|
||||||
response = JSON.parse(response);
|
|
||||||
if (response) {
|
|
||||||
$("#speedAlertValue").val(response.speedLimit);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setSpeed();
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function initStationaryAlert() {
|
|
||||||
// var serverUrl = "/portal/store/carbon.super/fs/gadget/geo-dashboard/controllers/get_alerts.jag?executionPlanType=Stationery&deviceId=" + deviceId;
|
|
||||||
var serverUrl = "/api/device-mgt/v1.0/geo-services/alerts/Stationery/" + deviceType + "/" + deviceId;
|
|
||||||
|
|
||||||
$(".removeGeoFence").tooltip();
|
|
||||||
invokerUtil.get(serverUrl, function (response) {
|
|
||||||
if (response) {
|
|
||||||
response = JSON.parse(response);
|
|
||||||
$(".fence-not-exist").hide();
|
|
||||||
for (var index in response) {
|
|
||||||
var alert = response[index];
|
|
||||||
$("#stationary-alert-table > tbody").append(
|
|
||||||
"<tr class='viewGeoFenceRow'style='cursor: pointer' data-stationeryTime='" + alert.stationaryTime +
|
|
||||||
"'data-fluctuationRadius='" + alert.fluctuationRadius + "'data-areaName='" + alert.areaName +
|
|
||||||
"'data-queryName='" + alert.queryName + "'data-geoJson=" + alert.geoJson + ">" +
|
|
||||||
"<td>" + alert.areaName + "</td><td>" + alert.stationaryTime + "</td><td>" + alert.fluctuationRadius +
|
|
||||||
"<td>" + alert.queryName + "</td><td>" + formatDate(new Date(alert.createdTime)) + "</td><td" +
|
|
||||||
" onClick=removeGeoFence(this.parentElement,'Stationery') data-toggle=" +
|
|
||||||
" 'tooltip' title='Remove fence' ><i class='fa fa-trash-o'></i></td></tr>")
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
$(".fence-not-exist").show();
|
|
||||||
$("#stationary-alert-table").hide();
|
|
||||||
}
|
|
||||||
$('.viewGeoFenceRow td:not(:last-child)').click(function () {
|
|
||||||
viewFence(this.parentElement,'Stationery');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
initStationaryAlert();
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function initializeWithin() {
|
|
||||||
$(".removeGeoFence").tooltip();
|
|
||||||
var serverUrl = "/api/device-mgt/v1.0/geo-services/alerts/Within/" + deviceType + "/" + deviceId;
|
|
||||||
invokerUtil.get(serverUrl, function (response) {
|
|
||||||
if (response) {
|
|
||||||
$(".fence-not-exist").hide();
|
|
||||||
response = JSON.parse(response);
|
|
||||||
for (var index in response) {
|
|
||||||
var alertBean = response[index];
|
|
||||||
$("#within-alert > tbody").append(
|
|
||||||
"<tr class='viewGeoFenceRow' style='cursor: pointer' data-areaName='" + alertBean.areaName +
|
|
||||||
"' data-queryName='" + alertBean.queryName + "'data-geoJson="+ alertBean.geoJson +"><td>" + alertBean.areaName + "</td>" +
|
|
||||||
"<td>" + alertBean.queryName + "</td><td>" + formatDate(new Date(alertBean.createdTime)) + "</td>" +
|
|
||||||
"<td onClick=removeGeoFence(this.parentElement,'Within') class='removeGeoFence'" +
|
|
||||||
" data-toggle='tooltip' title='Remove fence' ><i class='fa fa-trash-o'></i></td></tr>");
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
$(".fence-not-exist").show();
|
|
||||||
$("#within-alert").hide();
|
|
||||||
}
|
|
||||||
$('.viewGeoFenceRow td:not(:last-child)').click(function () {
|
|
||||||
viewFence(this.parentElement,'WithIn');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
initializeWithin();
|
|
@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
function reformatRadius(val){
|
|
||||||
if(val != "" && !isNaN(val)){
|
|
||||||
$("#fRadius" ).val(parseFloat(Math.round(val * 100) / 100).toFixed(2));
|
|
||||||
} else{
|
|
||||||
var message = "Invalid Fluctuation Radius Provided.";
|
|
||||||
noty({text: message, type: 'error'});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
@ -1,629 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var debugObject; // assign object and debug from browser console, this is for debugging purpose , unless this var is unused
|
|
||||||
var showPathFlag = false; // Flag to hold the status of draw objects path
|
|
||||||
var currentSpatialObjects = {};
|
|
||||||
var selectedSpatialObject; // This is set when user search for an object from the search box
|
|
||||||
var spatialWebsocket;
|
|
||||||
var onAlertWebsocket;
|
|
||||||
var onTrafficStreamWebsocket;
|
|
||||||
var currentPredictions = {};
|
|
||||||
// Make the function wait until the connection is made...
|
|
||||||
var waitTime = 1000;
|
|
||||||
var webSocketURL, alertWebSocketURL, trafficStreamWebSocketURL;
|
|
||||||
var deviceId;
|
|
||||||
var deviceType;
|
|
||||||
var isBatchModeOn = false;
|
|
||||||
var wsToken;
|
|
||||||
var geoPublicUri;
|
|
||||||
|
|
||||||
function processPointMessage(geoJsonFeature) {
|
|
||||||
if (geoJsonFeature.id in currentSpatialObjects) {
|
|
||||||
var excitingObject = currentSpatialObjects[geoJsonFeature.id];
|
|
||||||
excitingObject.update(geoJsonFeature);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var receivedObject = new SpatialObject(geoJsonFeature);
|
|
||||||
receivedObject.update(geoJsonFeature);
|
|
||||||
currentSpatialObjects[receivedObject.id] = receivedObject;
|
|
||||||
currentSpatialObjects[receivedObject.id].addTo(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onbeforeunload = function () {
|
|
||||||
disconnect();
|
|
||||||
};
|
|
||||||
|
|
||||||
function initializeSpatialStreamWebSocket() {
|
|
||||||
spatialWebsocket = new WebSocket(webSocketURL);
|
|
||||||
spatialWebsocket.onopen = webSocketSpatialOnOpen;
|
|
||||||
spatialWebsocket.onmessage = webSocketSpatialOnMessage;
|
|
||||||
spatialWebsocket.onclose = webSocketSpatialOnClose;
|
|
||||||
spatialWebsocket.onerror = webSocketSpatialOnError;
|
|
||||||
}
|
|
||||||
|
|
||||||
function initializeOnAlertWebSocket() {
|
|
||||||
onAlertWebsocket = new WebSocket(alertWebSocketURL);
|
|
||||||
onAlertWebsocket.onmessage = webSocketOnAlertMessage;
|
|
||||||
onAlertWebsocket.onclose = webSocketOnAlertClose;
|
|
||||||
onAlertWebsocket.onerror = webSocketOnAlertError;
|
|
||||||
onAlertWebsocket.onopen = webSocketOnAlertOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
function initializeGeoLocation(geoFencingEnabled) {
|
|
||||||
var deviceDetails = $(".device-id");
|
|
||||||
deviceId = deviceDetails.data("deviceid");
|
|
||||||
deviceType = deviceDetails.data("type");
|
|
||||||
if (deviceId && deviceType) {
|
|
||||||
var geoCharts = $("#geo-charts");
|
|
||||||
var wsEndPoint = geoCharts.data("ws-endpoint");
|
|
||||||
wsToken = geoCharts.data("ws-token");
|
|
||||||
geoPublicUri = geoCharts.data("geo-public-uri");
|
|
||||||
geoPublicUri = geoCharts.data("geo-public-uri");
|
|
||||||
webSocketURL = wsEndPoint + "iot.per.device.stream.geo.FusedSpatialEvent/1.0.0?"
|
|
||||||
+ "deviceId=" + deviceId + "&deviceType=" + deviceType + "&websocketToken=" + wsToken;
|
|
||||||
alertWebSocketURL = wsEndPoint + "iot.per.device.stream.geo.AlertsNotifications/1.0.0?"
|
|
||||||
+ "deviceId=" + deviceId + "&deviceType=" + deviceType + "&websocketToken=" + wsToken;
|
|
||||||
$("#proximity_alert").hide();
|
|
||||||
|
|
||||||
if (geoFencingEnabled) {
|
|
||||||
disconnect();
|
|
||||||
initializeSpatialStreamWebSocket();
|
|
||||||
initializeOnAlertWebSocket();
|
|
||||||
}
|
|
||||||
initialLoad(geoFencingEnabled);
|
|
||||||
InitSpatialObject(geoFencingEnabled);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
noty({text: 'Invalid Access! No device information provided to track!', type: 'error'});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function disconnect(){
|
|
||||||
if (spatialWebsocket && spatialWebsocket.readyState == spatialWebsocket.OPEN){
|
|
||||||
spatialWebsocket.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onAlertWebsocket && onAlertWebsocket.readyState == onAlertWebsocket.OPEN){
|
|
||||||
onAlertWebsocket.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function SpatialObject(json) {
|
|
||||||
this.id = json.id;
|
|
||||||
this.type = json.properties.type;
|
|
||||||
|
|
||||||
// Have to store the coordinates , to use when user wants to draw path
|
|
||||||
this.pathGeoJsons = []; // GeoJson standard MultiLineString(http://geojson.org/geojson-spec.html#id6) can't use here because this is a collection of paths(including property attributes)
|
|
||||||
this.path = []; // Path is an array of sections, where each section is a notified state of the path
|
|
||||||
|
|
||||||
|
|
||||||
this.speedHistory = new LocalStorageArray(this.id);
|
|
||||||
this.geoJson = L.geoJson(json, {
|
|
||||||
pointToLayer: function (feature, latlng) {
|
|
||||||
return L.marker(latlng, {icon: normalMovingIcon, iconAngle: this.heading});
|
|
||||||
}
|
|
||||||
}); // Create Leaflet GeoJson object
|
|
||||||
|
|
||||||
this.marker = this.geoJson.getLayers()[0];
|
|
||||||
this.marker.options.title = this.id;
|
|
||||||
|
|
||||||
if ("stationary" != this.type.toLowerCase() || "stop" != this.type.toLowerCase()) {
|
|
||||||
this.popupTemplate = $('#markerPopup');
|
|
||||||
} else {
|
|
||||||
this.popupTemplate = $('#markerPopupStop');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.marker.bindPopup(this.popupTemplate.html());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
function popupDateRange() {
|
|
||||||
$('#dateRangePopup').attr('title', 'Device ID - ' + deviceId + " Device Type - " + deviceType).dialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
SpatialObject.prototype.update = function (geoJSON) {
|
|
||||||
this.latitude = geoJSON.geometry.coordinates[1];
|
|
||||||
this.longitude = geoJSON.geometry.coordinates[0];
|
|
||||||
this.setSpeed(geoJSON.properties.speed);
|
|
||||||
this.state = geoJSON.properties.state;
|
|
||||||
this.heading = geoJSON.properties.heading;
|
|
||||||
|
|
||||||
this.information = geoJSON.properties.information;
|
|
||||||
this.type = geoJSON.properties.type;
|
|
||||||
|
|
||||||
if (this.type == "STOP") {
|
|
||||||
this.information = "Bus Stop";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (geoJSON.properties.notify) {
|
|
||||||
/*
|
|
||||||
//This is implemented in alertWebSocket
|
|
||||||
if (this.state != "NORMAL") {
|
|
||||||
notifyAlert("Object ID: <span style='color: blue;cursor: pointer' onclick='focusOnSpatialObject(" + this.id + ")'>" + this.id + "</span> change state to: <span style='color: red'>" + geoJSON.properties.state + "</span> Info : " + this.information);
|
|
||||||
}*/
|
|
||||||
var newLineStringGeoJson = this.createLineStringFeature(this.state, this.information, [this.latitude, this.longitude]);
|
|
||||||
this.pathGeoJsons.push(newLineStringGeoJson);
|
|
||||||
|
|
||||||
// only add the new path section to map if the spatial object is selected
|
|
||||||
if (selectedSpatialObject == this.id) {
|
|
||||||
var newPathSection = new L.polyline(newLineStringGeoJson.geometry.coordinates, this.getSectionStyles(geoJSON.properties.state));
|
|
||||||
newPathSection.bindPopup("Alert Information: " + newLineStringGeoJson.properties.information);
|
|
||||||
|
|
||||||
// Creating two sections joint // TODO : line color confusing , use diffrent color or seperator
|
|
||||||
var lastSection = this.path[this.path.length - 1].getLatLngs();
|
|
||||||
var joinLine = [lastSection[lastSection.length - 1], [this.latitude, this.longitude]];
|
|
||||||
var sectionJoin = new L.polyline(joinLine, this.getSectionStyles());
|
|
||||||
sectionJoin.setStyle({className: "sectionJointStyle"});// Make doted line for section join , this class is currently defined in map.jag as a inner css
|
|
||||||
|
|
||||||
this.path.push(sectionJoin);
|
|
||||||
this.path.push(newPathSection); // Order of the push matters , last polyLine object should be the `newPathSection` not the `sectionJoin`
|
|
||||||
|
|
||||||
sectionJoin.addTo(map);
|
|
||||||
newPathSection.addTo(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the spatial object leaflet marker
|
|
||||||
this.marker.setLatLng([this.latitude, this.longitude]);
|
|
||||||
|
|
||||||
if (this.latitude, this.longitude) {
|
|
||||||
map.setView([this.latitude, this.longitude]);
|
|
||||||
}
|
|
||||||
this.marker.setIconAngle(this.heading);
|
|
||||||
this.marker.setIcon(this.stateIcon());
|
|
||||||
|
|
||||||
if (this.pathGeoJsons.length > 0) {
|
|
||||||
// To prevent conflicts in
|
|
||||||
// Leaflet(http://leafletjs.com/reference.html#latlng) and geoJson standards(http://geojson.org/geojson-spec.html#id2),
|
|
||||||
// have to do this swapping, but the resulting geoJson in not upto geoJson standards
|
|
||||||
// TODO: write func to swap coordinates
|
|
||||||
this.pathGeoJsons[this.pathGeoJsons.length - 1].geometry.coordinates.push([geoJSON.geometry.coordinates[1], geoJSON.geometry.coordinates[0]]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newLineStringGeoJson = this.createLineStringFeature(this.state, this.information, [geoJSON.geometry.coordinates[1], geoJSON.geometry.coordinates[0]]);
|
|
||||||
this.pathGeoJsons.push(newLineStringGeoJson);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedSpatialObject == this.id) {
|
|
||||||
this.updatePath([geoJSON.geometry.coordinates[1], geoJSON.geometry.coordinates[0]]);
|
|
||||||
if (speedGraphControl) {
|
|
||||||
chart.load({columns: [this.speedHistory.getArray()]});
|
|
||||||
}
|
|
||||||
map.setView([this.latitude, this.longitude]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: use general popup DOM
|
|
||||||
this.popupTemplate.find('#objectId').html(this.id);
|
|
||||||
this.popupTemplate.find('#information').html(this.information);
|
|
||||||
|
|
||||||
this.popupTemplate.find('#speed').html(Math.round(this.speed * 10) / 10);
|
|
||||||
this.popupTemplate.find('#heading').html(angleToHeading(this.heading));
|
|
||||||
this.marker.setPopupContent(this.popupTemplate.html())
|
|
||||||
};
|
|
||||||
|
|
||||||
var headings = ["North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West", "NorthWest"];
|
|
||||||
|
|
||||||
function angleToHeading(angle) {
|
|
||||||
var angle = (angle + 360 + 22.5 ) % 360;
|
|
||||||
angle = Math.floor(angle / 45);
|
|
||||||
return headings[angle];
|
|
||||||
}
|
|
||||||
|
|
||||||
SpatialObject.prototype.removeFromMap = function () {
|
|
||||||
this.removePath();
|
|
||||||
this.marker.closePopup();
|
|
||||||
map.removeLayer(this.marker);
|
|
||||||
};
|
|
||||||
|
|
||||||
function clearMap() {
|
|
||||||
for (var spacialObject in currentSpatialObjects) {
|
|
||||||
currentSpatialObjects[spacialObject].removePath();
|
|
||||||
currentSpatialObjects[spacialObject].removeFromMap();
|
|
||||||
}
|
|
||||||
currentSpatialObjects = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
SpatialObject.prototype.createLineStringFeature = function (state, information, coordinates) {
|
|
||||||
return {
|
|
||||||
"type": "Feature",
|
|
||||||
"properties": {
|
|
||||||
"state": state,
|
|
||||||
"information": information
|
|
||||||
},
|
|
||||||
"geometry": {
|
|
||||||
"type": "LineString",
|
|
||||||
"coordinates": [coordinates]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
SpatialObject.prototype.setSpeed = function (speed) {
|
|
||||||
this.speed = speed;
|
|
||||||
this.speedHistory.push(speed);
|
|
||||||
if (this.speedHistory.length > ApplicationOptions.constance.SPEED_HISTORY_COUNT) {
|
|
||||||
this.speedHistory.splice(1, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SpatialObject.prototype.addTo = function (map) {
|
|
||||||
this.geoJson.addTo(map);
|
|
||||||
};
|
|
||||||
|
|
||||||
SpatialObject.prototype.updatePath = function (LatLng) {
|
|
||||||
this.path[this.path.length - 1].addLatLng(LatLng); // add LatLng to last section
|
|
||||||
};
|
|
||||||
|
|
||||||
SpatialObject.prototype.drawPath = function () {
|
|
||||||
var previousSectionLastPoint = []; // re init all the time when calls the function
|
|
||||||
if (this.path.length > 0) {
|
|
||||||
this.removePath();
|
|
||||||
// throw "geoDashboard error: path already exist,remove current path before drawing a new path, if need to update LatLngs use setLatLngs method instead"; // Path already exist
|
|
||||||
}
|
|
||||||
for (var lineString in this.pathGeoJsons) {
|
|
||||||
if (!this.pathGeoJsons.hasOwnProperty(lineString)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var currentSectionState = this.pathGeoJsons[lineString].properties.state;
|
|
||||||
var currentSection = new L.polyline(this.pathGeoJsons[lineString].geometry.coordinates, this.getSectionStyles(currentSectionState)); // Create path object when and only drawing the path (save memory) TODO: if need directly draw line from geojson
|
|
||||||
|
|
||||||
var currentSectionFirstPoint = this.pathGeoJsons[lineString].geometry.coordinates[0];
|
|
||||||
previousSectionLastPoint.push(currentSectionFirstPoint);
|
|
||||||
var sectionJoin = new L.polyline(previousSectionLastPoint, this.getSectionStyles());
|
|
||||||
sectionJoin.setStyle({className: "sectionJointStyle"});// Make doted line for section join , this class is currently defined in map.jag as a inner css
|
|
||||||
|
|
||||||
previousSectionLastPoint = [this.pathGeoJsons[lineString].geometry.coordinates[this.pathGeoJsons[lineString].geometry.coordinates.length - 1]];
|
|
||||||
sectionJoin.addTo(map);
|
|
||||||
this.path.push(sectionJoin);
|
|
||||||
currentSection.bindPopup("Alert Information: " + this.pathGeoJsons[lineString].properties.information);
|
|
||||||
currentSection.addTo(map);
|
|
||||||
this.path.push(currentSection);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SpatialObject.prototype.removePath = function () {
|
|
||||||
for (var section in this.path) {
|
|
||||||
if (this.path.hasOwnProperty(section)) {
|
|
||||||
map.removeLayer(this.path[section]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.path = []; // Clear the path layer (save memory)
|
|
||||||
};
|
|
||||||
|
|
||||||
SpatialObject.prototype.getSectionStyles = function (state) {
|
|
||||||
// TODO:<done> use option object to assign hardcode values
|
|
||||||
var pathColor;
|
|
||||||
switch (state) {
|
|
||||||
case "NORMAL":
|
|
||||||
pathColor = ApplicationOptions.colors.states.NORMAL; // Scope of function
|
|
||||||
break;
|
|
||||||
case "ALERTED":
|
|
||||||
pathColor = ApplicationOptions.colors.states.ALERTED;
|
|
||||||
break;
|
|
||||||
case "WARNING":
|
|
||||||
pathColor = ApplicationOptions.colors.states.WARNING;
|
|
||||||
break;
|
|
||||||
case "OFFLINE":
|
|
||||||
pathColor = ApplicationOptions.colors.states.OFFLINE;
|
|
||||||
break;
|
|
||||||
default: // TODO: set path var
|
|
||||||
return {color: ApplicationOptions.colors.states.UNKNOWN, weight: 8};
|
|
||||||
}
|
|
||||||
return {color: pathColor, weight: 8};
|
|
||||||
};
|
|
||||||
|
|
||||||
function processTrafficMessage(json) {
|
|
||||||
|
|
||||||
if (json.id in currentSpatialObjects) {
|
|
||||||
var existingObject = currentSpatialObjects[json.id];
|
|
||||||
existingObject.update(json);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var receivedObject = new GeoAreaObject(json);
|
|
||||||
currentSpatialObjects[json.id] = receivedObject;
|
|
||||||
currentSpatialObjects[json.id].addTo(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function processAlertMessage(json) {
|
|
||||||
if (json.state != "NORMAL" && json.state != "MINIMAL") {
|
|
||||||
notifyAlert("Object ID: <span style='color: blue;cursor: pointer' onclick='focusOnSpatialObject(" + json.id + ")'>" + json.id + "</span> change state to: <span style='color: red'>" + json.state + "</span> Info : " + json.information);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*function setPropertySafe(obj)
|
|
||||||
{
|
|
||||||
function isObject(o)
|
|
||||||
{
|
|
||||||
if (o === null) return false;
|
|
||||||
var type = typeof o;
|
|
||||||
return type === 'object' || type === 'function';
|
|
||||||
}
|
|
||||||
if (!isObject(obj)) return;
|
|
||||||
var prop;
|
|
||||||
for (var i=1; i < arguments.length-1; i++)
|
|
||||||
{
|
|
||||||
prop = arguments[i];
|
|
||||||
if (!isObject(obj[prop])) obj[prop] = {};
|
|
||||||
if (i < arguments.length-2) obj = obj[prop];
|
|
||||||
}
|
|
||||||
obj[prop] = arguments[i];
|
|
||||||
}*/
|
|
||||||
|
|
||||||
function processPredictionMessage(json) {
|
|
||||||
setPropertySafe(currentPredictions, json.day, json.hour, json.longitude, json.latitude, json.traffic - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
WebSocket.prototype.set_opened = function () {
|
|
||||||
this._opened = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
WebSocket.prototype.get_opened = function () {
|
|
||||||
return this._opened || false;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
var _longitudeStart = -0.0925
|
|
||||||
var _latitudeStart = 51.4985
|
|
||||||
var _unit = 0.005;
|
|
||||||
function requestPredictions(longitude, latitude, d) {
|
|
||||||
var serverUrl = "http://localhost:9763/endpoints/GpsDataOverHttp/predictionInput";
|
|
||||||
function loop(i) {
|
|
||||||
setTimeout(function() {
|
|
||||||
var data = {
|
|
||||||
day : d.getUTCDate() - 3,
|
|
||||||
hour : d.getUTCHours() + i + 1,
|
|
||||||
latitude : Math.round((latitude - _latitudeStart)/_unit),
|
|
||||||
longitude : Math.round((longitude - _longitudeStart)/_unit)
|
|
||||||
};
|
|
||||||
var json = JSON.stringify(data);
|
|
||||||
$.ajax({
|
|
||||||
url: serverUrl,
|
|
||||||
type: "POST",
|
|
||||||
data: json,
|
|
||||||
contentType: "application/json; charset=UTF-8"
|
|
||||||
});
|
|
||||||
if(i<6) {
|
|
||||||
loop(i+1);
|
|
||||||
}
|
|
||||||
},500);
|
|
||||||
}
|
|
||||||
loop(0);
|
|
||||||
}
|
|
||||||
var d= new Date();
|
|
||||||
//requestPredictions(-0.09,51.5,d);
|
|
||||||
function getPredictions(longitude, latitude, d) {
|
|
||||||
var longitude = Math.round((longitude - _longitudeStart)/_unit);
|
|
||||||
var latitude = Math.round((latitude - _latitudeStart)/_unit);
|
|
||||||
var traffic = [['x',0,0,0,0,0,0],['data',0,0,0,0,0,0]];
|
|
||||||
var hour = d.getUTCHours();
|
|
||||||
var day = d.getUTCDate() - 3;
|
|
||||||
for (var i = 0; i < 6; i++) {
|
|
||||||
hour = hour + 1;
|
|
||||||
if (hour > 23) {
|
|
||||||
hour = hour - 24;
|
|
||||||
day = day + 1;
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
traffic[0][i+1] = hour;
|
|
||||||
traffic[1][i+1] = currentPredictions[day][hour][longitude][latitude];
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return traffic;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
function GeoAreaObject(json) {
|
|
||||||
this.id = json.id;
|
|
||||||
this.type = "area";
|
|
||||||
|
|
||||||
var myStyle = {
|
|
||||||
"color": "#000001",
|
|
||||||
"weight": 5,
|
|
||||||
"opacity": 0,
|
|
||||||
"fillOpacity": 0.75
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (json.properties.state) {
|
|
||||||
case "Moderate":
|
|
||||||
myStyle["color"] = "#ffb13b";
|
|
||||||
break;
|
|
||||||
case "Severe":
|
|
||||||
myStyle["color"] = "#ff3f3f";
|
|
||||||
break;
|
|
||||||
case "Minimal":
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.geoJson = L.geoJson(json, {style: myStyle});
|
|
||||||
this.marker = this.geoJson.getLayers()[0];
|
|
||||||
this.marker.options.title = this.id;
|
|
||||||
this.popupTemplate = $('#areaPopup');
|
|
||||||
this.popupTemplate.find('#objectId').html(this.id);
|
|
||||||
this.popupTemplate.find('#severity').html(json.properties.state);
|
|
||||||
this.popupTemplate.find('#information').html(json.properties.information);
|
|
||||||
this.marker.bindPopup(this.popupTemplate.html());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
GeoAreaObject.prototype.addTo = function (map) {
|
|
||||||
this.geoJson.addTo(map);
|
|
||||||
};
|
|
||||||
|
|
||||||
GeoAreaObject.prototype.focusOn = function (map) {
|
|
||||||
map.fitBounds(this.geoJson);
|
|
||||||
};
|
|
||||||
|
|
||||||
GeoAreaObject.prototype.removeFromMap = function () {
|
|
||||||
map.removeLayer(this.geoJson);
|
|
||||||
};
|
|
||||||
|
|
||||||
GeoAreaObject.prototype.update = function (geoJSON) {
|
|
||||||
|
|
||||||
this.information = geoJSON.properties.information;
|
|
||||||
this.type = geoJSON.properties.type;
|
|
||||||
|
|
||||||
// Update the spatial object leaflet marker
|
|
||||||
this.marker.setLatLng([this.latitude, this.longitude]);
|
|
||||||
this.marker.setIconAngle(this.heading);
|
|
||||||
this.marker.setIcon(this.stateIcon());
|
|
||||||
|
|
||||||
// TODO: use general popup DOM
|
|
||||||
this.popupTemplate.find('#objectId').html(this.id);
|
|
||||||
this.popupTemplate.find('#information').html(this.information);
|
|
||||||
|
|
||||||
this.marker.setPopupContent(this.popupTemplate.html())
|
|
||||||
};
|
|
||||||
|
|
||||||
function notifyAlert(message) {
|
|
||||||
noty({text: "Alert: " + message, type: 'warning'});
|
|
||||||
}
|
|
||||||
|
|
||||||
function Alert(type, message, level) {
|
|
||||||
this.type = type;
|
|
||||||
this.message = message;
|
|
||||||
if (level)
|
|
||||||
this.level = level;
|
|
||||||
else
|
|
||||||
this.level = 'information';
|
|
||||||
|
|
||||||
this.notify = function () {
|
|
||||||
noty({text: this.type + ' ' + this.message, type: level});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function LocalStorageArray(id) {
|
|
||||||
if (typeof (sessionStorage) === 'undefined') {
|
|
||||||
// Sorry! No Web Storage support..
|
|
||||||
return ['speed']; // TODO: fetch this array from backend DB rather than keeping as in-memory array
|
|
||||||
}
|
|
||||||
if (id === undefined) {
|
|
||||||
throw 'Should provide an id to create a local storage!';
|
|
||||||
}
|
|
||||||
var DELIMITER = ','; // Private variable delimiter
|
|
||||||
this.storageId = id;
|
|
||||||
sessionStorage.setItem(id, 'speed'); // TODO: <note> even tho we use `sessionStorage` because of this line previous it get overwritten in each page refresh
|
|
||||||
this.getArray = function () {
|
|
||||||
return sessionStorage.getItem(this.storageId).split(DELIMITER);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.length = this.getArray().length;
|
|
||||||
|
|
||||||
this.push = function (value) {
|
|
||||||
var currentStorageValue = sessionStorage.getItem(this.storageId);
|
|
||||||
var updatedStorageValue;
|
|
||||||
if (currentStorageValue === null) {
|
|
||||||
updatedStorageValue = value;
|
|
||||||
} else {
|
|
||||||
updatedStorageValue = currentStorageValue + DELIMITER + value;
|
|
||||||
}
|
|
||||||
sessionStorage.setItem(this.storageId, updatedStorageValue);
|
|
||||||
this.length += 1;
|
|
||||||
};
|
|
||||||
this.isEmpty = function () {
|
|
||||||
return (this.getArray().length === 0);
|
|
||||||
};
|
|
||||||
this.splice = function (index, howmany) {
|
|
||||||
var currentArray = this.getArray();
|
|
||||||
currentArray.splice(index, howmany);
|
|
||||||
var updatedStorageValue = currentArray.toString();
|
|
||||||
sessionStorage.setItem(this.storageId, updatedStorageValue);
|
|
||||||
this.length -= howmany;
|
|
||||||
// TODO: should return spliced section as array
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var initLoading = true;
|
|
||||||
|
|
||||||
var webSocketOnAlertOpen = function () {
|
|
||||||
$('#ws-alert-stream').removeClass('text-muted text-danger text-success').addClass('text-success');
|
|
||||||
};
|
|
||||||
|
|
||||||
var webSocketOnAlertMessage = function processMessage(message) {
|
|
||||||
if (!isBatchModeOn) {
|
|
||||||
var json = $.parseJSON(message.data);
|
|
||||||
if (json.messageType == "Alert") {
|
|
||||||
processAlertMessage(json);
|
|
||||||
}else {
|
|
||||||
console.log("Message type not supported.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var webSocketOnAlertClose = function (e) {
|
|
||||||
};
|
|
||||||
|
|
||||||
var webSocketOnAlertError = function (e) {
|
|
||||||
noty({text: 'Something went wrong when trying to connect to <b>' + alertWebSocketURL + '<b/>', type: 'error'});
|
|
||||||
};
|
|
||||||
|
|
||||||
var webSocketSpatialOnOpen = function () {
|
|
||||||
if (initLoading) {
|
|
||||||
initLoading = false;
|
|
||||||
}
|
|
||||||
$('#ws-spatial-stream').removeClass('text-muted text-danger text-success').addClass('text-success');
|
|
||||||
};
|
|
||||||
|
|
||||||
var webSocketSpatialOnMessage = function (message) {
|
|
||||||
if (!isBatchModeOn) {
|
|
||||||
var json = $.parseJSON(message.data);
|
|
||||||
if (json.messageType == "Point") {
|
|
||||||
processPointMessage(json);
|
|
||||||
} else if (json.messageType == "Prediction") {
|
|
||||||
//processPredictionMessage(json);
|
|
||||||
} else {
|
|
||||||
console.log("Message type not supported.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var webSocketSpatialOnClose = function (e) {
|
|
||||||
};
|
|
||||||
|
|
||||||
var webSocketSpatialOnError = function (err) {
|
|
||||||
noty({text: 'Something went wrong when trying to connect to <b>' + webSocketURL + '<b/>', type: 'error'});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
SpatialObject.prototype.stateIcon = function () {
|
|
||||||
//TODO : Need to add separate icons for each device type
|
|
||||||
var iconUrl = geoPublicUri + "/img/markers/object-types/default";
|
|
||||||
if (0 < this.speed && (-360 <= this.heading && 360 >= this.heading)) {
|
|
||||||
iconUrl = iconUrl + "/moving/" + this.state.toLowerCase();
|
|
||||||
} else {
|
|
||||||
iconUrl = iconUrl + "/non-moving/" + this.state.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
return L.icon({
|
|
||||||
iconUrl: iconUrl + ".png",
|
|
||||||
shadowUrl: false,
|
|
||||||
iconSize: [24, 24],
|
|
||||||
iconAnchor: [+12, +12],
|
|
||||||
popupAnchor: [-2, -5]
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var normalMovingIcon = L.icon({
|
|
||||||
iconUrl: ApplicationOptions.leaflet.iconUrls.normalMovingIcon,
|
|
||||||
shadowUrl: false,
|
|
||||||
iconSize: [24, 24],
|
|
||||||
iconAnchor: [+12, +12],
|
|
||||||
popupAnchor: [-2, -5]
|
|
||||||
});
|
|
Loading…
Reference in new issue