Device Location history view feature

merge-requests/271/head^2^2
achala piyarathna 5 years ago committed by Dharmakeerthi Lasantha
parent 852518f9af
commit 5b50cddea6

@ -11,13 +11,18 @@
"bootstrap": "^4.3.1", "bootstrap": "^4.3.1",
"javascript-time-ago": "^2.0.1", "javascript-time-ago": "^2.0.1",
"keymirror": "^0.1.1", "keymirror": "^0.1.1",
"leaflet": "^1.3.4",
"leaflet-routing-machine": "^3.2.12",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"moment": "^2.24.0", "moment": "latest",
"prop-types": "latest",
"rc-viewer": "0.0.9", "rc-viewer": "0.0.9",
"react-bootstrap": "^1.0.0-beta.12", "react-advanced-datetimerange-picker": "^1.0.8",
"react-highlight-words": "^0.16.0", "react-highlight-words": "^0.16.0",
"react-image-viewer-zoom": "^1.0.36", "react-image-viewer-zoom": "^1.0.36",
"react-infinite-scroller": "^1.2.4", "react-infinite-scroller": "^1.2.4",
"react-leaflet": "^2.4.0",
"react-bootstrap": "^1.0.0-beta.12",
"react-moment": "^0.9.2", "react-moment": "^0.9.2",
"react-router": "^5.0.1", "react-router": "^5.0.1",
"react-router-config": "^5.0.1", "react-router-config": "^5.0.1",

@ -33,5 +33,10 @@
"color": "#008cc4", "color": "#008cc4",
"theme": "filled" "theme": "filled"
} }
},
"geoMap": {
"url": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
"attribution": "&copy; <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors",
"defaultZoomLevel": 16
} }
} }

@ -0,0 +1,636 @@
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg,
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer {
max-width: none !important;
max-height: none !important;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
/* Fallback for FF which doesn't support pinch-zoom */
touch-action: none;
touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-container {
-webkit-tap-highlight-color: transparent;
}
.leaflet-container a {
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile {
will-change: opacity;
}
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline: 0;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-container a.leaflet-active {
outline: 2px solid orange;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a,
.leaflet-bar a:hover {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
.leaflet-touch .leaflet-bar a:first-child {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
.leaflet-touch .leaflet-bar a:last-child {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
font-size: 22px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
overflow-x: hidden;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path {
background-image: url(images/marker-icon.png);
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.7);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover {
text-decoration: underline;
}
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-scale {
font-size: 11px;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: #fff;
background: rgba(255, 255, 255, 0.5);
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 19px;
line-height: 1.4;
}
.leaflet-popup-content p {
margin: 18px 0;
}
.leaflet-popup-tip-container {
width: 40px;
height: 20px;
position: absolute;
left: 50%;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
border: none;
text-align: center;
width: 18px;
height: 14px;
font: 16px/14px Tahoma, Verdana, sans-serif;
color: #c3c3c3;
text-decoration: none;
font-weight: bold;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover {
color: #999;
}
.leaflet-popup-scrolled {
overflow: auto;
border-bottom: 1px solid #ddd;
border-top: 1px solid #ddd;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-popup-tip-container {
margin-top: -1px;
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-clickable {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}

@ -0,0 +1,81 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.
*/
import React, {Component, Fragment} from "react";
import {
Map,
TileLayer,
Marker,
Polyline, Popup, Tooltip
} from "react-leaflet";
import {withConfigContext} from "../../../context/ConfigContext";
class GeoCustomMap extends Component {
constructor(props) {
super(props);
}
/**
* Polyline draw for historical locations
* @param locationData - location data object
* @returns content
*/
polylineMarker = (locationData) => {
const polyMarkers = locationData
.map(locationPoint => {
return [locationPoint.latitude, locationPoint.longitude]
});
return (
<div style={{display: "none"}}>{
<Polyline color="green" positions={polyMarkers}>
<Popup>on the way</Popup>
</Polyline>
}</div>
);
};
render() {
const locationData = this.props.locationData;
const config = this.props.context;
const attribution = config.geoMap.attribution;
const url = config.geoMap.url;
const startingPoint = [locationData[0].latitude, locationData[0].longitude];
const zoom = config.geoMap.defaultZoomLevel;
return (
<div style={{backgroundColor: "#ffffff", borderRadius: 5, padding: 5}}>
<Map center={startingPoint} zoom={zoom}>
<TileLayer
url={url}
attribution={attribution}
/>
<Fragment>
{this.polylineMarker(locationData)}
<Marker position={startingPoint}>
<Tooltip>Starting Location</Tooltip>
</Marker>
</Fragment>
</Map>
</div>
);
}
}
export default withConfigContext(GeoCustomMap);

@ -0,0 +1,10 @@
.leaflet-container {
align-content: center;
padding-top: 80px;
height: 550px;
width: 100%;
}
.controllerDiv {
padding-bottom: 30px;
}

@ -0,0 +1,292 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.
*/
import React from "react";
import moment from "moment";
import DateTimeRangeContainer from "react-advanced-datetimerange-picker";
import {Button, Select, message, notification, Tag, Tooltip, Empty} from "antd";
import axios from "axios";
import {withConfigContext} from "../../../context/ConfigContext";
import GeoCustomMap from "../geo-custom-map/GeoCustomMap";
import "./GeoDashboard.css";
class GeoDashboard extends React.Component {
constructor(props) {
super(props);
let start = moment(new Date());
let end = moment(start)
.add(5, "days")
.subtract(1, "minute");
this.state = {
deviceData: [],
selectedDevice: '',
locationData: [],
// currentLocation: [],
loading: false,
start: start,
end: end,
buttonTooltip: "Fetch Locations",
};
}
componentDidMount() {
this.fetchDevices();
// this.fetchCurrentLocation();
}
/**
* Call back on apply button in the date time picker
* @param startDate - start date
* @param endDate - end date
*/
applyCallback = (startDate, endDate) => {
console.log("Apply Callback");
this.setState({
start: startDate,
end: endDate
});
};
/**
* Api call handle on fetch location date button
*/
handleApiCall = () => {
if (this.state.selectedDevice && this.state.start && this.state.end) {
const toInMills = moment(this.state.end);
const fromInMills = moment(this.state.start);
const deviceType = this.state.selectedDevice.type;
const deviceId = this.state.selectedDevice.deviceIdentifier;
const config = this.props.context;
this.setState({loading: true});
axios.get(window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt
+ "/devices/" + deviceType + "/" + deviceId + "/location-history?" + "from=" + fromInMills + "&to=" +
toInMills,).then(res => {
if (res.status === 200) {
const locationData = JSON.parse(res.data.data);
this.setState({
loading: false,
locationData,
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to fetch locations......",
});
}
this.setState({loading: false});
console.log(error);
});
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Please provide a date range and a device.",
});
}
};
/**
* Device dropdown list handler
* @param e - selected device data
*/
handleDeviceList = (e) => {
let selectedDevice = this.state.deviceData[e];
this.setState({selectedDevice})
};
/**
* render fetch location button
*/
fetchLocationButton = () => {
let flag;
let toolTip = "";
if (this.state.selectedDevice === "") {
flag = true;
toolTip = "Please select a Device";
}
return (
<Tooltip placement="rightBottom" title={toolTip}>
<Button disabled={flag}
onClick={this.handleApiCall}>
Fetch Locations
</Button>
</Tooltip>);
};
/**
* fetches device data to populate the dropdown list
*/
fetchDevices = () => {
const config = this.props.context;
this.setState({loading: true});
axios.get(
window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt +
"/devices?excludeStatus=REMOVED",).then(res => {
if (res.status === 200) {
this.setState({
loading: false,
deviceData: res.data.data.devices,
});
}
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification["error"]({
message: "There was a problem",
duration: 0,
description:
"Error occurred while trying to load devices.",
});
}
this.setState({loading: false});
});
};
/**
* Geo Dashboard controller
*/
controllerBar = () => {
let now = new Date();
let start = moment(
new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0)
);
let end = moment(start)
.add(1, "days")
.subtract(1, "seconds");
let ranges = {
"Today Only": [moment(start), moment(end)],
"Yesterday Only": [
moment(start).subtract(1, "days"),
moment(end).subtract(1, "days")
],
"3 Days": [moment(start).subtract(3, "days"), moment(end)],
"5 Days": [moment(start).subtract(5, "days"), moment(end)],
"1 Week": [moment(start).subtract(7, "days"), moment(end)],
"2 Weeks": [moment(start).subtract(14, "days"), moment(end)],
"1 Month": [moment(start).subtract(1, "months"), moment(end)],
};
let local = {
format: "DD-MM-YYYY HH:mm",
sundayFirst: false
};
let maxDate = moment(start).add(24, "hour");
let value =
`
${this.state.start.format("DD-MM-YYYY HH:mm")} - ${this.state.end.format("DD-MM-YYYY HH:mm")}
`;
let {deviceData} = this.state;
return (
<div className="controllerDiv">
<Button style={{marginRight: 20}}>
<DateTimeRangeContainer
ranges={ranges}
start={this.state.start}
end={this.state.end}
local={local}
maxDate={maxDate}
applyCallback={this.applyCallback}
>
{value}
</DateTimeRangeContainer>
</Button>
<Select
showSearch
style={{width: 220, marginRight: 20}}
placeholder="Select a Device"
optionFilterProp="children"
onChange={this.handleDeviceList}
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{deviceData.map((device, index) =>
<Select.Option key={index} value={index}>
{device.name + " "}{this.statusTag(device)}
</Select.Option>)}
</Select>
{this.fetchLocationButton()}
</div>
);
};
/**
* Creates color based tags on device status
* @param device - device object
*/
statusTag = (device) => {
const status = device.enrolmentInfo.status.toLowerCase();
let color = "#f9ca24";
switch (status) {
case "active":
color = "#badc58";
break;
case "created":
color = "#6ab04c";
break;
case "inactive":
color = "#f9ca24";
break;
case "blocked":
color = "#636e72";
break;
}
return <Tag color={color}>{status}</Tag>
};
render() {
const locationData = [...this.state.locationData];
return (
<div className="container">
{this.controllerBar()}
{(locationData.length > 0) ?
<GeoCustomMap locationData={locationData}/>
:
<Empty/>
}
</div>
);
}
}
export default withConfigContext(GeoDashboard);

@ -21,6 +21,7 @@
<head> <head>
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/>
<title>Entgra Device Management</title> <title>Entgra Device Management</title>
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.3/leaflet.css'>
</head> </head>
<div id="root"></div> <div id="root"></div>
</html> </html>

@ -25,7 +25,7 @@ import {
Card Card
} from "antd"; } from "antd";
import {Link} from "react-router-dom"; import {Link} from "react-router-dom";
import DeviceTable from "../../../components/Devices/DevicesTable"; import GeoDashboard from "../../../components/Geo/geo-dashboard/GeoDashboard";
const {Paragraph} = Typography; const {Paragraph} = Typography;
@ -50,12 +50,11 @@ class Geo extends React.Component {
</Breadcrumb> </Breadcrumb>
<div className="wrap"> <div className="wrap">
<h3>Geo</h3> <h3>Geo</h3>
<Paragraph>Lorem ipsum dolor sit amet, est similique constituto at, quot inermis id mel, an <Paragraph>Geo Location Service</Paragraph>
illud incorrupte nam.</Paragraph>
</div> </div>
</PageHeader> </PageHeader>
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}> <div style={{background: '#f0f2f5', padding: 24, minHeight: 720, alignItems: "center"}}>
<GeoDashboard/>
</div> </div>
</div> </div>
); );

@ -269,6 +269,13 @@ public interface DeviceManagementService {
@QueryParam("ownership") @QueryParam("ownership")
@Size(max = 45) @Size(max = 45)
String ownership, String ownership,
@ApiParam(
name = "excludeStatus",
value = "Provide the devices that excludes the given status",
required = false)
@QueryParam("excludeStatus")
@Size(max = 45)
String excludeStatus,
@ApiParam( @ApiParam(
name = "status", name = "status",
value = "Provide the device status details, such as active or inactive.", value = "Provide the device status details, such as active or inactive.",
@ -476,6 +483,78 @@ public interface DeviceManagementService {
@HeaderParam("If-Modified-Since") @HeaderParam("If-Modified-Since")
String ifModifiedSince); String ifModifiedSince);
@GET
@Path("/{deviceType}/{deviceId}/location-history")
@ApiOperation(
consumes = "application/json",
produces = "application/json",
httpMethod = "GET",
value = "Getting the Location Details of a Device",
notes = "Get the location details of a device during a define time period.",
response = Response.class,
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:details")
})
}
)
@ApiResponses(value = {
@ApiResponse(
code = 200,
message = "OK.",
response = Response.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid Device Identifiers found.",
response = Response.class),
@ApiResponse(
code = 401,
message = "Unauthorized. \n Unauthorized request."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error on retrieving stats",
response = Response.class)
})
Response getDeviceLocationInfo(
@ApiParam(
name = "device-type",
value = "The device type, such as ios, android, or windows.",
required = true)
@PathParam("deviceType")
@Size(max = 45)
String deviceType,
@ApiParam(
name = "deviceId",
value = "The device ID.",
required = true)
@PathParam("deviceId") String deviceId,
@ApiParam(
name = "from",
value = "Define the time to start getting the geo location history of the device in " +
"milliseconds.",
required = true)
@QueryParam("from") long from,
@ApiParam(
name = "to",
value = "Define the time to finish getting the geo location history of the device in " +
"milliseconds.",
required = true)
@QueryParam("to") long to);
@GET @GET
@Path("/type/any/id/{id}") @Path("/type/any/id/{id}")
@ApiOperation( @ApiOperation(

@ -42,13 +42,9 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.Feature; import org.wso2.carbon.device.mgt.common.Feature;
import org.wso2.carbon.device.mgt.common.FeatureManager; import org.wso2.carbon.device.mgt.common.FeatureManager;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidConfigurationException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.app.mgt.Application;
@ -57,6 +53,11 @@ import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorization
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidConfigurationException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
@ -80,6 +81,7 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationList; import org.wso2.carbon.device.mgt.jaxrs.beans.OperationList;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationRequest; import org.wso2.carbon.device.mgt.jaxrs.beans.OperationRequest;
import org.wso2.carbon.device.mgt.jaxrs.service.api.DeviceManagementService; import org.wso2.carbon.device.mgt.jaxrs.service.api.DeviceManagementService;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil;
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
import org.wso2.carbon.policy.mgt.common.PolicyManagementException; import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
@ -145,6 +147,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@QueryParam("role") String role, @QueryParam("role") String role,
@QueryParam("ownership") String ownership, @QueryParam("ownership") String ownership,
@QueryParam("status") String status, @QueryParam("status") String status,
@QueryParam("excludeStatus") String excludeStatus,
@QueryParam("groupId") int groupId, @QueryParam("groupId") int groupId,
@QueryParam("since") String since, @QueryParam("since") String since,
@HeaderParam("If-Modified-Since") String ifModifiedSince, @HeaderParam("If-Modified-Since") String ifModifiedSince,
@ -186,6 +189,10 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
RequestValidationUtil.validateStatus(status); RequestValidationUtil.validateStatus(status);
request.setStatus(status); request.setStatus(status);
} }
if (excludeStatus != null && !excludeStatus.isEmpty()) {
RequestValidationUtil.validateStatus(excludeStatus);
request.setExcludeStatus(excludeStatus);
}
if (groupId != 0) { if (groupId != 0) {
request.setGroupId(groupId); request.setGroupId(groupId);
} }
@ -466,6 +473,68 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
return Response.status(Response.Status.OK).entity(device).build(); return Response.status(Response.Status.OK).entity(device).build();
} }
@Path("/{deviceType}/{deviceId}/location-history")
@GET
@Consumes("application/json")
@Produces("application/json")
public Response getDeviceLocationInfo(@PathParam("deviceType") String deviceType,
@PathParam("deviceId") String deviceId,
@QueryParam("from") long from, @QueryParam("to") long to) {
List<DeviceLocationHistory> deviceLocationHistory;
String errorMessage;
try {
RequestValidationUtil.validateDeviceIdentifier(deviceType, deviceId);
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
DeviceAccessAuthorizationService deviceAccessAuthorizationService =
DeviceMgtAPIUtils.getDeviceAccessAuthorizationService();
String authorizedUser = CarbonContext.getThreadLocalCarbonContext().getUsername();
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(deviceId, deviceType);
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(deviceType);
if (deviceAccessAuthorizationService == null) {
errorMessage = "Device access authorization service is failed";
log.error(errorMessage);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(errorMessage).build()).build();
}
if (!deviceAccessAuthorizationService.isUserAuthorized(deviceIdentifier, authorizedUser)) {
String msg = "User '" + authorizedUser + "' is not authorized to retrieve the given device id '" +
deviceId + "'";
log.error(msg);
return Response.status(Response.Status.UNAUTHORIZED).entity(
new ErrorResponse.ErrorResponseBuilder().setCode(401l).setMessage(msg).build()).build();
}
if (from == 0 || to == 0) {
errorMessage = "Invalid values for from/to";
log.error(errorMessage);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(errorMessage)).build();
}
deviceLocationHistory = dms.getDeviceLocationInfo(deviceIdentifier, from, to);
} catch (DeviceManagementException e) {
errorMessage = "Error occurred while fetching the device information.";
log.error(errorMessage, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(errorMessage).build()).build();
} catch (DeviceAccessAuthorizationException e) {
errorMessage = "Error occurred while checking the device authorization.";
log.error(errorMessage, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(errorMessage).build()).build();
} catch (InputValidationException e){
errorMessage = "Invalid device Id or device type";
log.error(errorMessage, e);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(errorMessage)).build();
}
return Response.status(Response.Status.OK).entity(deviceLocationHistory).build();
}
@GET @GET
@Path("/type/any/id/{id}") @Path("/type/any/id/{id}")
@Override @Override

@ -105,6 +105,7 @@ public class DeviceManagementServiceImplTest {
private static final String DEFAULT_ROLE = "admin"; private static final String DEFAULT_ROLE = "admin";
private static final String DEFAULT_OWNERSHIP = "BYOD"; private static final String DEFAULT_OWNERSHIP = "BYOD";
private static final String DEFAULT_STATUS = "ACTIVE"; private static final String DEFAULT_STATUS = "ACTIVE";
private static final String DEFAULT_EXCLUDED_STATUS = "REMOVE";
private static final String DEFAULT_DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z"; private static final String DEFAULT_DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z";
private DeviceManagementService deviceManagementService; private DeviceManagementService deviceManagementService;
private DeviceAccessAuthorizationService deviceAccessAuthorizationService; private DeviceAccessAuthorizationService deviceAccessAuthorizationService;
@ -173,7 +174,7 @@ public class DeviceManagementServiceImplTest {
.toReturn(this.deviceAccessAuthorizationService); .toReturn(this.deviceAccessAuthorizationService);
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
} }
@ -190,19 +191,19 @@ public class DeviceManagementServiceImplTest {
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
response = this.deviceManagementService response = this.deviceManagementService
.getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, null, DEFAULT_OWNERSHIP, .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, null, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
response = this.deviceManagementService response = this.deviceManagementService
.getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, null, null, null, DEFAULT_OWNERSHIP, .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, null, null, null, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
response = this.deviceManagementService response = this.deviceManagementService
.getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, null, null, null, DEFAULT_OWNERSHIP, .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, null, null, null, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, true, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, true, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
} }
@ -311,7 +312,7 @@ public class DeviceManagementServiceImplTest {
.toReturn(null); .toReturn(null);
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
} }
@ -329,11 +330,11 @@ public class DeviceManagementServiceImplTest {
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
response = this.deviceManagementService response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, null, DEFAULT_USERNAME, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, null, DEFAULT_USERNAME, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
} }
@ -352,8 +353,8 @@ public class DeviceManagementServiceImplTest {
Mockito.when(this.deviceAccessAuthorizationService.isDeviceAdminUser()).thenReturn(false); Mockito.when(this.deviceAccessAuthorizationService.isDeviceAdminUser()).thenReturn(false);
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, "newuser", null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, DEFAULT_STATUS, 1, .getDevices(null, TEST_DEVICE_TYPE, "newuser", null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, DEFAULT_EXCLUDED_STATUS,
null, null, false, 10, 5); DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode());
Mockito.reset(this.deviceAccessAuthorizationService); Mockito.reset(this.deviceAccessAuthorizationService);
} }
@ -372,15 +373,15 @@ public class DeviceManagementServiceImplTest {
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, ifModifiedSince, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, ifModifiedSince, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.NOT_MODIFIED.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.NOT_MODIFIED.getStatusCode());
response = this.deviceManagementService response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, ifModifiedSince, true, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, ifModifiedSince, true, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.NOT_MODIFIED.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.NOT_MODIFIED.getStatusCode());
response = this.deviceManagementService response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, "ErrorModifiedSince", false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, "ErrorModifiedSince", false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
} }
@ -398,15 +399,15 @@ public class DeviceManagementServiceImplTest {
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, since, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, since, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
response = this.deviceManagementService response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, since, null, true, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, since, null, true, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
response = this.deviceManagementService response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, "ErrorSince", null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, "ErrorSince", null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
} }
@ -426,7 +427,7 @@ public class DeviceManagementServiceImplTest {
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
Mockito.reset(this.deviceManagementProviderService); Mockito.reset(this.deviceManagementProviderService);
} }
@ -446,7 +447,7 @@ public class DeviceManagementServiceImplTest {
Response response = this.deviceManagementService Response response = this.deviceManagementService
.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP,
DEFAULT_STATUS, 1, null, null, false, 10, 5); DEFAULT_EXCLUDED_STATUS, DEFAULT_STATUS, 1, null, null, false, 10, 5);
Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
Mockito.reset(this.deviceAccessAuthorizationService); Mockito.reset(this.deviceAccessAuthorizationService);
} }

@ -33,6 +33,7 @@ public class PaginationRequest {
private String owner; private String owner;
private String ownerPattern; private String ownerPattern;
private String status; private String status;
private String excludeStatus;
private String deviceType; private String deviceType;
private String deviceName; private String deviceName;
private String ownership; private String ownership;
@ -85,6 +86,14 @@ public class PaginationRequest {
this.status = status; this.status = status;
} }
public String getExcludeStatus() {
return excludeStatus;
}
public void setExcludeStatus(String excludeStatus) {
this.excludeStatus = excludeStatus;
}
public String getDeviceType() { public String getDeviceType() {
return deviceType; return deviceType;
} }

@ -55,6 +55,46 @@ public class DeviceLocation implements Serializable {
private String country; private String country;
@ApiModelProperty(name = "updatedTime", value = "Update time of the device.", required = true) @ApiModelProperty(name = "updatedTime", value = "Update time of the device.", required = true)
private Date updatedTime; private Date updatedTime;
@ApiModelProperty(name = "altitude", value = "Device altitude.", required = true)
private Double altitude;
@ApiModelProperty(name = "speed", value = "Device speed.", required = true)
private Float speed;
@ApiModelProperty(name = "bearing", value = "Device bearing.", required = true)
private Float bearing;
@ApiModelProperty(name = "distance", value = "Device distance.", required = true)
private Double distance;
public Double getDistance() {
return distance;
}
public void setDistance(Double distance) {
this.distance = distance;
}
public Double getAltitude() {
return altitude;
}
public Float getSpeed() {
return speed;
}
public void setSpeed(Float speed) {
this.speed = speed;
}
public Float getBearing() {
return bearing;
}
public void setBearing(Float bearing) {
this.bearing = bearing;
}
public void setAltitude(Double altitude) {
this.altitude = altitude;
}
public int getDeviceId() { public int getDeviceId() {
return deviceId; return deviceId;

@ -0,0 +1,164 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.
*/
package org.wso2.carbon.device.mgt.common.device.details;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
@ApiModel(value = "DeviceLocationHistory", description = "This class carries all information related to the device location History" +
"details provided by a device.")
public class DeviceLocationHistory implements Serializable {
@ApiModelProperty(name = "deviceId", value = "Device id", required = true)
private int deviceId;
@ApiModelProperty(name = "geoHash", value = "Geo Hash", required = true)
private String geoHash;
@ApiModelProperty(name = "deviceType", value = "Device type", required = true)
private String deviceType;
@ApiModelProperty(name = "deviceIdentifier", value = "Device Id Name", required = true)
private String deviceIdentifier;
@ApiModelProperty(name = "latitude", value = "Device GPS latitude.", required = true)
private Double latitude;
@ApiModelProperty(name = "longitude", value = "Device GPS longitude.", required = true)
private Double longitude;
@ApiModelProperty(name = "tenantId", value = "Tenant Id.", required = true)
private int tenantId;
@ApiModelProperty(name = "altitude", value = "Device altitude.", required = true)
private Double altitude;
@ApiModelProperty(name = "speed", value = "Device speed.", required = true)
private Float speed;
@ApiModelProperty(name = "bearing", value = "Device bearing.", required = true)
private Float bearing;
@ApiModelProperty(name = "distance", value = "Device distance.", required = true)
private Double distance;
@ApiModelProperty(name = "timestamp", value = "Timestamp.", required = true)
private Long timestamp;
@ApiModelProperty(name = "owner", value = "Owner.", required = true)
private String owner;
public DeviceLocationHistory() {
}
public String getGeoHash() {
return geoHash;
}
public void setGeoHash(String geoHash) {
this.geoHash = geoHash;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
public int getDeviceId() {
return deviceId;
}
public void setDeviceId(int deviceId) {
this.deviceId = deviceId;
}
public String getDeviceIdentifier() {
return deviceIdentifier;
}
public void setDeviceIdentifier(String deviceIdentifier) {
this.deviceIdentifier = deviceIdentifier;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public int getTenantId() {
return tenantId;
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
public Double getAltitude() {
return altitude;
}
public void setAltitude(double altitude) {
this.altitude = altitude;
}
public Float getSpeed() {
return speed;
}
public void setSpeed(Float speed) {
this.speed = speed;
}
public Float getBearing() {
return bearing;
}
public void setBearing(Float bearing) {
this.bearing = bearing;
}
public Double getDistance() {
return distance;
}
public void setDistance(Double distance) {
this.distance = distance;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
}

@ -40,6 +40,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status; import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo; import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.geo.GeoCluster; import org.wso2.carbon.device.mgt.core.geo.GeoCluster;
@ -550,4 +551,15 @@ public interface DeviceDAO {
int tenantId, int tenantId,
String fromDate, String fromDate,
String toDate) throws DeviceManagementDAOException; String toDate) throws DeviceManagementDAOException;
/**
* Retrieve device location information
* @param deviceIdentifier Device Identifier object
* @param from Specified start timestamp
* @param to Specified end timestamp
* @return
* @throws DeviceManagementDAOException
*/
List<DeviceLocationHistory> getDeviceLocationInfo(DeviceIdentifier deviceIdentifier, long from, long to)
throws DeviceManagementDAOException;
} }

@ -42,6 +42,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status; import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo; import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.core.dao.DeviceDAO; import org.wso2.carbon.device.mgt.core.dao.DeviceDAO;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException;
@ -939,6 +940,8 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
boolean isOwnershipProvided = false; boolean isOwnershipProvided = false;
String status = request.getStatus(); String status = request.getStatus();
boolean isStatusProvided = false; boolean isStatusProvided = false;
String excludeStatus = request.getExcludeStatus();
boolean isExcludeStatusProvided = false;
Date since = request.getSince(); Date since = request.getSince();
boolean isSinceProvided = false; boolean isSinceProvided = false;
try { try {
@ -987,6 +990,11 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
isStatusProvided = true; isStatusProvided = true;
} }
if (excludeStatus != null && !excludeStatus.isEmpty()) {
sql = sql + " AND e.STATUS != ?";
isExcludeStatusProvided = true;
}
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
stmt.setInt(1, tenantId); stmt.setInt(1, tenantId);
int paramIdx = 2; int paramIdx = 2;
@ -1012,6 +1020,9 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
if (isStatusProvided) { if (isStatusProvided) {
stmt.setString(paramIdx++, request.getStatus()); stmt.setString(paramIdx++, request.getStatus());
} }
if (isExcludeStatusProvided) {
stmt.setString(paramIdx++, excludeStatus);
}
rs = stmt.executeQuery(); rs = stmt.executeQuery();
if (rs.next()) { if (rs.next()) {
deviceCount = rs.getInt("DEVICE_COUNT"); deviceCount = rs.getInt("DEVICE_COUNT");
@ -1574,6 +1585,44 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
} }
@Override @Override
public List<DeviceLocationHistory> getDeviceLocationInfo(DeviceIdentifier deviceIdentifier, long from, long to)
throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
List<DeviceLocationHistory> deviceLocationHistories = new ArrayList<>();
try {
conn = this.getConnection();
String sql =
"SELECT DEVICE_ID, TENANT_ID, DEVICE_ID_NAME, DEVICE_TYPE_NAME, LATITUDE, LONGITUDE, SPEED, " +
"HEADING, TIMESTAMP, GEO_HASH, DEVICE_OWNER, DEVICE_ALTITUDE, DISTANCE " +
"FROM DM_DEVICE_HISTORY_LAST_SEVEN_DAYS " +
"WHERE DEVICE_ID_NAME = ? " +
"AND DEVICE_TYPE_NAME = ? " +
"AND TIMESTAMP >= ? " +
"AND TIMESTAMP <= ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, deviceIdentifier.getId());
stmt.setString(2, deviceIdentifier.getType());
stmt.setLong(3, from);
stmt.setLong(4, to);
rs = stmt.executeQuery();
while (rs.next()) {
deviceLocationHistories.add(DeviceManagementDAOUtil.loadDeviceLocation(rs));
}
} catch (SQLException e) {
String errMessage = "Error occurred while obtaining the DB connection to get device location information";
log.error(errMessage, e);
throw new DeviceManagementDAOException(errMessage, e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return deviceLocationHistories;
}
public void deleteDevices(List<String> deviceIdentifiers, List<Integer> deviceIds, List<Integer> enrollmentIds) public void deleteDevices(List<String> deviceIdentifiers, List<Integer> deviceIds, List<Integer> enrollmentIds)
throws DeviceManagementDAOException { throws DeviceManagementDAOException {
Connection conn; Connection conn;

@ -61,6 +61,8 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
boolean isOwnershipProvided = false; boolean isOwnershipProvided = false;
String status = request.getStatus(); String status = request.getStatus();
boolean isStatusProvided = false; boolean isStatusProvided = false;
String excludeStatus = request.getExcludeStatus();
boolean isExcludeStatusProvided = false;
Date since = request.getSince(); Date since = request.getSince();
boolean isSinceProvided = false; boolean isSinceProvided = false;
try { try {
@ -115,6 +117,11 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
sql = sql + " AND e.STATUS = ?"; sql = sql + " AND e.STATUS = ?";
isStatusProvided = true; isStatusProvided = true;
} }
//Add the query for exclude status
if (excludeStatus != null && !excludeStatus.isEmpty()) {
sql = sql + " AND e.STATUS != ?";
isExcludeStatusProvided = true;
}
sql = sql + " LIMIT ?,?"; sql = sql + " LIMIT ?,?";
@ -143,6 +150,9 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
if (isStatusProvided) { if (isStatusProvided) {
stmt.setString(paramIdx++, status); stmt.setString(paramIdx++, status);
} }
if (isExcludeStatusProvided) {
stmt.setString(paramIdx++, excludeStatus);
}
stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx++, request.getStartIndex());
stmt.setInt(paramIdx, request.getRowCount()); stmt.setInt(paramIdx, request.getRowCount());
rs = stmt.executeQuery(); rs = stmt.executeQuery();
@ -182,6 +192,8 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
boolean isOwnershipProvided = false; boolean isOwnershipProvided = false;
String status = request.getStatus(); String status = request.getStatus();
boolean isStatusProvided = false; boolean isStatusProvided = false;
String excludeStatus = request.getExcludeStatus();
boolean isExcludeStatusProvided = false;
Date since = request.getSince(); Date since = request.getSince();
boolean isSinceProvided = false; boolean isSinceProvided = false;
@ -242,6 +254,11 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
sql = sql + " AND e.STATUS = ?"; sql = sql + " AND e.STATUS = ?";
isStatusProvided = true; isStatusProvided = true;
} }
//Add the query for exclude status
if (excludeStatus != null && !excludeStatus.isEmpty()) {
sql = sql + " AND e.STATUS != ?";
isExcludeStatusProvided = true;
}
sql = sql + " LIMIT ?,?"; sql = sql + " LIMIT ?,?";
@ -273,6 +290,9 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
if (isStatusProvided) { if (isStatusProvided) {
stmt.setString(paramIdx++, status); stmt.setString(paramIdx++, status);
} }
if (isExcludeStatusProvided) {
stmt.setString(paramIdx++, excludeStatus);
}
stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx++, request.getStartIndex());
stmt.setInt(paramIdx, request.getRowCount()); stmt.setInt(paramIdx, request.getRowCount());

@ -64,6 +64,8 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl {
boolean isOwnershipProvided = false; boolean isOwnershipProvided = false;
String status = request.getStatus(); String status = request.getStatus();
boolean isStatusProvided = false; boolean isStatusProvided = false;
String excludeStatus = request.getExcludeStatus();
boolean isExcludeStatusProvided = false;
Date since = request.getSince(); Date since = request.getSince();
boolean isSinceProvided = false; boolean isSinceProvided = false;
try { try {
@ -118,6 +120,11 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl {
sql = sql + " AND e.STATUS = ?"; sql = sql + " AND e.STATUS = ?";
isStatusProvided = true; isStatusProvided = true;
} }
//Add the query for exclude status
if (excludeStatus != null && !excludeStatus.isEmpty()) {
sql = sql + " AND e.STATUS != ?";
isExcludeStatusProvided = true;
}
sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
@ -146,6 +153,9 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl {
if (isStatusProvided) { if (isStatusProvided) {
stmt.setString(paramIdx++, status); stmt.setString(paramIdx++, status);
} }
if (isExcludeStatusProvided) {
stmt.setString(paramIdx++, excludeStatus);
}
stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx++, request.getStartIndex());
stmt.setInt(paramIdx, request.getRowCount()); stmt.setInt(paramIdx, request.getRowCount());
rs = stmt.executeQuery(); rs = stmt.executeQuery();
@ -184,6 +194,8 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl {
boolean isOwnershipProvided = false; boolean isOwnershipProvided = false;
String status = request.getStatus(); String status = request.getStatus();
boolean isStatusProvided = false; boolean isStatusProvided = false;
String excludeStatus = request.getExcludeStatus();
boolean isExcludeStatusProvided = false;
Date since = request.getSince(); Date since = request.getSince();
boolean isSinceProvided = false; boolean isSinceProvided = false;
@ -244,6 +256,11 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl {
sql = sql + " AND e.STATUS = ?"; sql = sql + " AND e.STATUS = ?";
isStatusProvided = true; isStatusProvided = true;
} }
//Add the query for exclude status
if (excludeStatus != null && !excludeStatus.isEmpty()) {
sql = sql + " AND e.STATUS != ?";
isExcludeStatusProvided = true;
}
sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
@ -275,6 +292,9 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl {
if (isStatusProvided) { if (isStatusProvided) {
stmt.setString(paramIdx++, status); stmt.setString(paramIdx++, status);
} }
if (isExcludeStatusProvided) {
stmt.setString(paramIdx++, excludeStatus);
}
stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx++, request.getStartIndex());
stmt.setInt(paramIdx, request.getRowCount()); stmt.setInt(paramIdx, request.getRowCount());

@ -61,6 +61,8 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl {
boolean isOwnershipProvided = false; boolean isOwnershipProvided = false;
String status = request.getStatus(); String status = request.getStatus();
boolean isStatusProvided = false; boolean isStatusProvided = false;
String excludeStatus = request.getExcludeStatus();
boolean isExcludeStatusProvided = false;
Date since = request.getSince(); Date since = request.getSince();
boolean isSinceProvided = false; boolean isSinceProvided = false;
try { try {
@ -102,6 +104,11 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl {
sql = sql + " AND e.STATUS = ?"; sql = sql + " AND e.STATUS = ?";
isStatusProvided = true; isStatusProvided = true;
} }
//Add the query for exclude status
if (excludeStatus != null && !excludeStatus.isEmpty()) {
sql = sql + " AND e.STATUS != ?";
isExcludeStatusProvided = true;
}
sql = sql + " LIMIT ? OFFSET ?"; sql = sql + " LIMIT ? OFFSET ?";
@ -127,6 +134,9 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl {
if (isStatusProvided) { if (isStatusProvided) {
stmt.setString(paramIdx++, status); stmt.setString(paramIdx++, status);
} }
if (isExcludeStatusProvided) {
stmt.setString(paramIdx++, excludeStatus);
}
stmt.setInt(paramIdx++, request.getRowCount()); stmt.setInt(paramIdx++, request.getRowCount());
stmt.setInt(paramIdx, request.getStartIndex()); stmt.setInt(paramIdx, request.getStartIndex());
rs = stmt.executeQuery(); rs = stmt.executeQuery();
@ -165,6 +175,8 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl {
boolean isOwnershipProvided = false; boolean isOwnershipProvided = false;
String status = request.getStatus(); String status = request.getStatus();
boolean isStatusProvided = false; boolean isStatusProvided = false;
String excludeStatus = request.getExcludeStatus();
boolean isExcludeStatusProvided = false;
Date since = request.getSince(); Date since = request.getSince();
boolean isSinceProvided = false; boolean isSinceProvided = false;
@ -225,6 +237,11 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl {
sql = sql + " AND e.STATUS = ?"; sql = sql + " AND e.STATUS = ?";
isStatusProvided = true; isStatusProvided = true;
} }
//Add the query for exclude status
if (excludeStatus != null && !excludeStatus.isEmpty()) {
sql = sql + " AND e.STATUS != ?";
isExcludeStatusProvided = true;
}
sql = sql + " LIMIT ? OFFSET ?"; sql = sql + " LIMIT ? OFFSET ?";
@ -256,6 +273,9 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl {
if (isStatusProvided) { if (isStatusProvided) {
stmt.setString(paramIdx++, status); stmt.setString(paramIdx++, status);
} }
if (isExcludeStatusProvided) {
stmt.setString(paramIdx++, excludeStatus);
}
stmt.setInt(paramIdx, request.getRowCount()); stmt.setInt(paramIdx, request.getRowCount());
stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx++, request.getStartIndex());

@ -61,6 +61,8 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl {
boolean isOwnershipProvided = false; boolean isOwnershipProvided = false;
String status = request.getStatus(); String status = request.getStatus();
boolean isStatusProvided = false; boolean isStatusProvided = false;
String excludeStatus = request.getExcludeStatus();
boolean isExcludeStatusProvided = false;
Date since = request.getSince(); Date since = request.getSince();
boolean isSinceProvided = false; boolean isSinceProvided = false;
try { try {
@ -115,6 +117,11 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl {
sql = sql + " AND e.STATUS = ?"; sql = sql + " AND e.STATUS = ?";
isStatusProvided = true; isStatusProvided = true;
} }
//Add the query for exclude status
if (excludeStatus != null && !excludeStatus.isEmpty()) {
sql = sql + " AND e.STATUS != ?";
isExcludeStatusProvided = true;
}
sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
@ -143,6 +150,9 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl {
if (isStatusProvided) { if (isStatusProvided) {
stmt.setString(paramIdx++, status); stmt.setString(paramIdx++, status);
} }
if (isExcludeStatusProvided) {
stmt.setString(paramIdx++, excludeStatus);
}
stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx++, request.getStartIndex());
stmt.setInt(paramIdx, request.getRowCount()); stmt.setInt(paramIdx, request.getRowCount());
rs = stmt.executeQuery(); rs = stmt.executeQuery();
@ -181,6 +191,8 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl {
boolean isOwnershipProvided = false; boolean isOwnershipProvided = false;
String status = request.getStatus(); String status = request.getStatus();
boolean isStatusProvided = false; boolean isStatusProvided = false;
String excludeStatus = request.getExcludeStatus();
boolean isExcludeStatusProvided = false;
Date since = request.getSince(); Date since = request.getSince();
boolean isSinceProvided = false; boolean isSinceProvided = false;
@ -241,6 +253,11 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl {
sql = sql + " AND e.STATUS = ?"; sql = sql + " AND e.STATUS = ?";
isStatusProvided = true; isStatusProvided = true;
} }
//Add the query for exclude status
if (excludeStatus != null && !excludeStatus.isEmpty()) {
sql = sql + " AND e.STATUS != ?";
isExcludeStatusProvided = true;
}
sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
@ -272,6 +289,9 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl {
if (isStatusProvided) { if (isStatusProvided) {
stmt.setString(paramIdx++, status); stmt.setString(paramIdx++, status);
} }
if (isExcludeStatusProvided) {
stmt.setString(paramIdx++, excludeStatus);
}
stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx++, request.getStartIndex());
stmt.setInt(paramIdx, request.getRowCount()); stmt.setInt(paramIdx, request.getRowCount());

@ -23,6 +23,8 @@ import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException;
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
@ -245,4 +247,23 @@ public final class DeviceManagementDAOUtil {
deviceInfo.setUpdatedTime(new java.util.Date(rs.getLong("UPDATE_TIMESTAMP"))); deviceInfo.setUpdatedTime(new java.util.Date(rs.getLong("UPDATE_TIMESTAMP")));
return deviceInfo; return deviceInfo;
} }
public static DeviceLocationHistory loadDeviceLocation(ResultSet rs) throws SQLException {
DeviceLocationHistory deviceLocationHistory = new DeviceLocationHistory();
deviceLocationHistory.setDeviceId(rs.getInt("DEVICE_ID"));
deviceLocationHistory.setDeviceIdentifier(rs.getString("DEVICE_ID_NAME"));
deviceLocationHistory.setTenantId(rs.getInt("TENANT_ID"));
deviceLocationHistory.setDeviceType(rs.getString("DEVICE_TYPE_NAME"));
deviceLocationHistory.setLatitude(rs.getDouble("LATITUDE"));
deviceLocationHistory.setLongitude(rs.getDouble("LONGITUDE"));
deviceLocationHistory.setSpeed(rs.getFloat("SPEED"));
deviceLocationHistory.setBearing(rs.getFloat("HEADING"));
deviceLocationHistory.setAltitude(rs.getDouble("DEVICE_ALTITUDE"));
deviceLocationHistory.setDistance(rs.getDouble("DISTANCE"));
deviceLocationHistory.setOwner(rs.getString("DEVICE_OWNER"));
deviceLocationHistory.setTimestamp(rs.getLong("TIMESTAMP"));
deviceLocationHistory.setGeoHash(rs.getString("GEO_HASH"));
return deviceLocationHistory;
}
} }

@ -19,9 +19,12 @@
package org.wso2.carbon.device.mgt.core.device.details.mgt; package org.wso2.carbon.device.mgt.core.device.details.mgt;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException;
import java.util.List; import java.util.List;

@ -0,0 +1,4 @@
package org.wso2.carbon.device.mgt.core.device.details.mgt;
public interface LocationCallback {
}

@ -19,6 +19,8 @@
package org.wso2.carbon.device.mgt.core.device.details.mgt.dao; package org.wso2.carbon.device.mgt.core.device.details.mgt.dao;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
@ -100,6 +102,16 @@ public interface DeviceDetailsDAO {
*/ */
void deleteDeviceLocation(int deviceId, int enrollmentId) throws DeviceDetailsMgtDAOException; void deleteDeviceLocation(int deviceId, int enrollmentId) throws DeviceDetailsMgtDAOException;
/**
* Add device location information to the database
* @param device Device object
* @param deviceLocation Device Location Object
* @param tenantId Tenant Id
* @throws DeviceDetailsMgtDAOException
*/
void addDeviceLocationInfo(Device device, DeviceLocation deviceLocation, int tenantId)
throws DeviceDetailsMgtDAOException;
// /** // /**
// * This method will add device application to database. // * This method will add device application to database.
// * @param deviceApplication - Device application // * @param deviceApplication - Device application

@ -21,6 +21,8 @@ package org.wso2.carbon.device.mgt.core.device.details.mgt.dao.impl;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory;
@ -238,8 +240,9 @@ public class DeviceDetailsDAOImpl implements DeviceDetailsDAO {
try { try {
conn = this.getConnection(); conn = this.getConnection();
stmt = conn.prepareStatement("INSERT INTO DM_DEVICE_LOCATION (DEVICE_ID, LATITUDE, LONGITUDE, STREET1, " + stmt = conn.prepareStatement("INSERT INTO DM_DEVICE_LOCATION (DEVICE_ID, LATITUDE, LONGITUDE, STREET1, " +
"STREET2, CITY, ZIP, STATE, COUNTRY, GEO_HASH, UPDATE_TIMESTAMP, ENROLMENT_ID) " + "STREET2, CITY, ZIP, STATE, COUNTRY, GEO_HASH, UPDATE_TIMESTAMP, ENROLMENT_ID, ALTITUDE, SPEED, BEARING, " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); "DISTANCE) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
stmt.setInt(1, deviceLocation.getDeviceId()); stmt.setInt(1, deviceLocation.getDeviceId());
stmt.setDouble(2, deviceLocation.getLatitude()); stmt.setDouble(2, deviceLocation.getLatitude());
stmt.setDouble(3, deviceLocation.getLongitude()); stmt.setDouble(3, deviceLocation.getLongitude());
@ -252,6 +255,10 @@ public class DeviceDetailsDAOImpl implements DeviceDetailsDAO {
stmt.setString(10, GeoHashGenerator.encodeGeohash(deviceLocation)); stmt.setString(10, GeoHashGenerator.encodeGeohash(deviceLocation));
stmt.setLong(11, System.currentTimeMillis()); stmt.setLong(11, System.currentTimeMillis());
stmt.setInt(12, enrollmentId); stmt.setInt(12, enrollmentId);
stmt.setDouble(13, deviceLocation.getAltitude());
stmt.setFloat(14, deviceLocation.getSpeed());
stmt.setFloat(15, deviceLocation.getBearing());
stmt.setDouble(16, deviceLocation.getDistance());
stmt.execute(); stmt.execute();
} catch (SQLException e) { } catch (SQLException e) {
throw new DeviceDetailsMgtDAOException("Error occurred while adding the device location to database.", e); throw new DeviceDetailsMgtDAOException("Error occurred while adding the device location to database.", e);
@ -317,6 +324,45 @@ public class DeviceDetailsDAOImpl implements DeviceDetailsDAO {
} }
} }
@Override
public void addDeviceLocationInfo(Device device, DeviceLocation deviceLocation, int tenantId)
throws DeviceDetailsMgtDAOException {
Connection conn;
PreparedStatement stmt = null;
String errMessage;
try {
conn = this.getConnection();
stmt = conn.prepareStatement(
"INSERT INTO " +
"DM_DEVICE_HISTORY_LAST_SEVEN_DAYS " +
"(DEVICE_ID, DEVICE_ID_NAME, TENANT_ID, DEVICE_TYPE_NAME, LATITUDE, LONGITUDE, SPEED, HEADING, " +
"TIMESTAMP, GEO_HASH, DEVICE_OWNER, DEVICE_ALTITUDE, DISTANCE) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
stmt.setInt(1, device.getId());
stmt.setString(2, device.getDeviceIdentifier());
stmt.setInt(3, tenantId);
stmt.setString(4, device.getType());
stmt.setDouble(5, deviceLocation.getLatitude());
stmt.setDouble(6, deviceLocation.getLongitude());
stmt.setFloat(7, deviceLocation.getSpeed());
stmt.setFloat(8, deviceLocation.getBearing());
stmt.setLong(9, System.currentTimeMillis());
stmt.setString(10, GeoHashGenerator.encodeGeohash(deviceLocation));
stmt.setString(11, device.getEnrolmentInfo().getOwner());
stmt.setDouble(12, deviceLocation.getAltitude());
stmt.setDouble(13, deviceLocation.getDistance());
stmt.execute();
} catch (SQLException e) {
errMessage = "Error occurred while updating the device location information to database.";
log.error(errMessage);
throw new DeviceDetailsMgtDAOException(errMessage, e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, null);
}
}
private Connection getConnection() throws SQLException { private Connection getConnection() throws SQLException {
return DeviceManagementDAOFactory.getConnection(); return DeviceManagementDAOFactory.getConnection();
} }

@ -54,7 +54,6 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager {
private static final String LOCATION_EVENT_STREAM_DEFINITION = "org.wso2.iot.LocationStream"; private static final String LOCATION_EVENT_STREAM_DEFINITION = "org.wso2.iot.LocationStream";
private static final String DEVICE_INFO_EVENT_STREAM_DEFINITION = "org.wso2.iot.DeviceInfoStream"; private static final String DEVICE_INFO_EVENT_STREAM_DEFINITION = "org.wso2.iot.DeviceInfoStream";
public DeviceInformationManagerImpl() { public DeviceInformationManagerImpl() {
this.deviceDAO = DeviceManagementDAOFactory.getDeviceDAO(); this.deviceDAO = DeviceManagementDAOFactory.getDeviceDAO();
this.deviceDetailsDAO = DeviceManagementDAOFactory.getDeviceDetailsDAO(); this.deviceDetailsDAO = DeviceManagementDAOFactory.getDeviceDetailsDAO();
@ -212,6 +211,8 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager {
deviceLocation.setDeviceId(device.getId()); deviceLocation.setDeviceId(device.getId());
DeviceManagementDAOFactory.beginTransaction(); DeviceManagementDAOFactory.beginTransaction();
deviceDAO.updateDevice(device, CarbonContext.getThreadLocalCarbonContext().getTenantId()); deviceDAO.updateDevice(device, CarbonContext.getThreadLocalCarbonContext().getTenantId());
deviceDetailsDAO.addDeviceLocationInfo(device, deviceLocation,
CarbonContext.getThreadLocalCarbonContext().getTenantId());
deviceDetailsDAO.deleteDeviceLocation(deviceLocation.getDeviceId(), device.getEnrolmentInfo().getId()); deviceDetailsDAO.deleteDeviceLocation(deviceLocation.getDeviceId(), device.getEnrolmentInfo().getId());
deviceDetailsDAO.addDeviceLocation(deviceLocation, device.getEnrolmentInfo().getId()); deviceDetailsDAO.addDeviceLocation(deviceLocation, device.getEnrolmentInfo().getId());
if (DeviceManagerUtil.isPublishLocationResponseEnabled()) { if (DeviceManagerUtil.isPublishLocationResponseEnabled()) {
@ -219,7 +220,11 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager {
Object[] payload = new Object[]{ Object[] payload = new Object[]{
deviceLocation.getUpdatedTime().getTime(), deviceLocation.getUpdatedTime().getTime(),
deviceLocation.getLatitude(), deviceLocation.getLatitude(),
deviceLocation.getLongitude() deviceLocation.getLongitude(),
deviceLocation.getAltitude(),
deviceLocation.getSpeed(),
deviceLocation.getBearing(),
deviceLocation.getDistance()
}; };
DeviceManagerUtil.getEventPublisherService().publishEvent( DeviceManagerUtil.getEventPublisherService().publishEvent(
LOCATION_EVENT_STREAM_DEFINITION, "1.0.0", metaData, new Object[0], payload LOCATION_EVENT_STREAM_DEFINITION, "1.0.0", metaData, new Object[0], payload

@ -55,6 +55,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfiguratio
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.license.mgt.License; import org.wso2.carbon.device.mgt.common.license.mgt.License;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
@ -715,6 +716,18 @@ public interface DeviceManagementProviderService {
*/ */
List<DeviceType> getDeviceTypes() throws DeviceManagementException; List<DeviceType> getDeviceTypes() throws DeviceManagementException;
/**
* This retrieves the device location histories
*
* @param deviceIdentifier Device Identifier object
* @param from Specified start timestamp
* @param to Specified end timestamp
* @throws DeviceManagementException
* @return list of device's location histories
*/
List<DeviceLocationHistory> getDeviceLocationInfo(DeviceIdentifier deviceIdentifier, long from, long to)
throws DeviceManagementException;
/** /**
* This retrieves the device pull notification payload and passes to device type pull notification subscriber. * This retrieves the device pull notification payload and passes to device type pull notification subscriber.
* @throws PullNotificationExecutionFailedException * @throws PullNotificationExecutionFailedException

@ -79,6 +79,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistory;
import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotificationConfiguration; import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotificationConfiguration;
import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotifier; import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotifier;
import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotifierException; import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotifierException;
@ -2822,6 +2823,36 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
} }
} }
@Override
public List<DeviceLocationHistory> getDeviceLocationInfo(DeviceIdentifier deviceIdentifier, long from, long to)
throws DeviceManagementException {
if (log.isDebugEnabled()) {
log.debug("Get device location information");
}
List<DeviceLocationHistory> deviceLocationHistory;
String errMessage;
try {
DeviceManagementDAOFactory.openConnection();
deviceLocationHistory = deviceDAO.getDeviceLocationInfo(deviceIdentifier, from, to);
} catch (DeviceManagementDAOException e) {
errMessage = "Error occurred in getDeviceLocationInfo";
log.error(errMessage, e);
throw new DeviceManagementException(errMessage, e);
} catch (SQLException e) {
errMessage = "Error occurred while opening a connection to the data source";
log.error(errMessage, e);
throw new DeviceManagementException(errMessage, e);
} finally {
DeviceManagementDAOFactory.closeConnection();
}
return deviceLocationHistory;
}
@Override @Override
public void notifyPullNotificationSubscriber(DeviceIdentifier deviceIdentifier, Operation operation) public void notifyPullNotificationSubscriber(DeviceIdentifier deviceIdentifier, Operation operation)
throws PullNotificationExecutionFailedException { throws PullNotificationExecutionFailedException {
@ -3159,11 +3190,19 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
} }
} }
/**
* Extracting device location properties
* @param device Device object
*/
private void extractDeviceLocationToUpdate(Device device) { private void extractDeviceLocationToUpdate(Device device) {
List<Device.Property> properties = device.getProperties(); List<Device.Property> properties = device.getProperties();
if (properties != null) { if (properties != null) {
String latitude = null; String latitude = null;
String longitude = null; String longitude = null;
String altitude = null;
String speed = null;
String bearing = null;
String distance = null;
for (Device.Property p : properties) { for (Device.Property p : properties) {
if (p.getName().equalsIgnoreCase("latitude")) { if (p.getName().equalsIgnoreCase("latitude")) {
latitude = p.getValue(); latitude = p.getValue();
@ -3171,6 +3210,18 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
if (p.getName().equalsIgnoreCase("longitude")) { if (p.getName().equalsIgnoreCase("longitude")) {
longitude = p.getValue(); longitude = p.getValue();
} }
if (p.getName().equalsIgnoreCase("altitude")) {
altitude = p.getValue();
}
if (p.getName().equalsIgnoreCase("speed")) {
speed = p.getValue();
}
if (p.getName().equalsIgnoreCase("bearing")) {
bearing = p.getValue();
}
if (p.getName().equalsIgnoreCase("distance")) {
distance = p.getValue();
}
} }
if (latitude != null && longitude != null && !latitude.isEmpty() && !longitude.isEmpty()) { if (latitude != null && longitude != null && !latitude.isEmpty() && !longitude.isEmpty()) {
DeviceLocation deviceLocation = new DeviceLocation(); DeviceLocation deviceLocation = new DeviceLocation();
@ -3178,8 +3229,12 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
deviceLocation.setDeviceIdentifier(new DeviceIdentifier(device.getDeviceIdentifier(), deviceLocation.setDeviceIdentifier(new DeviceIdentifier(device.getDeviceIdentifier(),
device.getType())); device.getType()));
try { try {
deviceLocation.setAltitude(Double.parseDouble(altitude));
deviceLocation.setLatitude(Double.parseDouble(latitude)); deviceLocation.setLatitude(Double.parseDouble(latitude));
deviceLocation.setLongitude(Double.parseDouble(longitude)); deviceLocation.setLongitude(Double.parseDouble(longitude));
deviceLocation.setDistance(Double.parseDouble(distance));
deviceLocation.setSpeed(Float.parseFloat(speed));
deviceLocation.setBearing(Float.parseFloat(bearing));
DeviceInformationManager deviceInformationManager = new DeviceInformationManagerImpl(); DeviceInformationManager deviceInformationManager = new DeviceInformationManagerImpl();
deviceInformationManager.addDeviceLocation(deviceLocation); deviceInformationManager.addDeviceLocation(deviceLocation);
} catch (Exception e) { } catch (Exception e) {
@ -3187,7 +3242,8 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
// a warning for reference. // a warning for reference.
log.warn("Error occurred while trying to add '" + device.getType() + "' device '" + log.warn("Error occurred while trying to add '" + device.getType() + "' device '" +
device.getDeviceIdentifier() + "' (id:'" + device.getId() + "') location (lat:" + latitude + device.getDeviceIdentifier() + "' (id:'" + device.getId() + "') location (lat:" + latitude +
", lon:" + longitude + ") due to:" + e.getMessage()); ", lon:" + longitude + ", altitude: " + altitude +
", speed: " + speed + ", bearing:" + bearing + ", distance: " + distance + ") due to:" + e.getMessage());
} }
} }
} }

@ -458,6 +458,10 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_LOCATION (
COUNTRY VARCHAR(45) NULL, COUNTRY VARCHAR(45) NULL,
GEO_HASH VARCHAR(45) NULL, GEO_HASH VARCHAR(45) NULL,
UPDATE_TIMESTAMP BIGINT(15) NOT NULL, UPDATE_TIMESTAMP BIGINT(15) NOT NULL,
ALTITUDE DOUBLE NULL,
SPEED FLOAT NULL,
BEARING FLOAT NULL,
DISTANCE DOUBLE NULL,
PRIMARY KEY (ID), PRIMARY KEY (ID),
CONSTRAINT DM_DEVICE_LOCATION_DEVICE CONSTRAINT DM_DEVICE_LOCATION_DEVICE
FOREIGN KEY (DEVICE_ID) FOREIGN KEY (DEVICE_ID)
@ -505,6 +509,25 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_DETAIL (
ON UPDATE NO ACTION ON UPDATE NO ACTION
); );
CREATE TABLE IF NOT EXISTS DM_DEVICE_HISTORY_LAST_SEVEN_DAYS
(
ID INTEGER AUTO_INCREMENT NOT NULL,
DEVICE_ID INT NOT NULL,
DEVICE_ID_NAME VARCHAR(255) NOT NULL,
TENANT_ID INT NOT NULL,
DEVICE_TYPE_NAME VARCHAR(45) NOT NULL,
LATITUDE DOUBLE NULL,
LONGITUDE DOUBLE NULL,
SPEED FLOAT NULL,
HEADING FLOAT NULL,
TIMESTAMP BIGINT(15) NOT NULL,
GEO_HASH VARCHAR(45) NULL,
DEVICE_OWNER VARCHAR(45) NULL,
DEVICE_ALTITUDE DOUBLE NULL,
DISTANCE DOUBLE NULL,
PRIMARY KEY (ID)
);
-- POLICY AND DEVICE GROUP MAPPING -- -- POLICY AND DEVICE GROUP MAPPING --
CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_POLICY ( CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_POLICY (
ID INT NOT NULL AUTO_INCREMENT, ID INT NOT NULL AUTO_INCREMENT,

@ -507,6 +507,10 @@ CREATE TABLE DM_DEVICE_LOCATION (
COUNTRY VARCHAR(45) NULL, COUNTRY VARCHAR(45) NULL,
GEO_HASH VARCHAR(45) NULL, GEO_HASH VARCHAR(45) NULL,
UPDATE_TIMESTAMP BIGINT NOT NULL, UPDATE_TIMESTAMP BIGINT NOT NULL,
ALTITUDE FLOAT NULL,
SPEED FLOAT NULL,
BEARING FLOAT NULL,
DISTANCE FLOAT NULL,
PRIMARY KEY (ID), PRIMARY KEY (ID),
INDEX DM_DEVICE_LOCATION_DEVICE_idx (DEVICE_ID ASC), INDEX DM_DEVICE_LOCATION_DEVICE_idx (DEVICE_ID ASC),
INDEX DM_DEVICE_LOCATION_GEO_hashx (GEO_HASH ASC), INDEX DM_DEVICE_LOCATION_GEO_hashx (GEO_HASH ASC),
@ -523,6 +527,26 @@ CREATE TABLE DM_DEVICE_LOCATION (
ON UPDATE NO ACTION ON UPDATE NO ACTION
); );
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_HISTORY_LAST_SEVEN_DAYS]') AND TYPE IN (N'U'))
CREATE TABLE IF NOT EXISTS DM_DEVICE_HISTORY_LAST_SEVEN_DAYS
(
ID INTEGER IDENTITY (1,1) NOT NULL,
DEVICE_ID INTEGER NOT NULL,
DEVICE_ID_NAME VARCHAR(255) NOT NULL,
TENANT_ID INTEGER NOT NULL,
DEVICE_TYPE_NAME VARCHAR(45) NOT NULL,
LATITUDE FLOAT NULL,
LONGITUDE FLOAT NULL,
SPEED FLOAT NULL,
HEADING FLOAT NULL,
TIMESTAMP BIGINT(15) NOT NULL,
GEO_HASH VARCHAR(45) NULL,
DEVICE_OWNER VARCHAR(45) NULL,
DEVICE_ALTITUDE FLOAT NULL,
DISTANCE FLOAT NULL,
PRIMARY KEY (ID)
);
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_DETAIL]') AND TYPE IN (N'U')) IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_DETAIL]') AND TYPE IN (N'U'))
CREATE TABLE DM_DEVICE_DETAIL ( CREATE TABLE DM_DEVICE_DETAIL (
ID INTEGER IDENTITY(1,1) NOT NULL, ID INTEGER IDENTITY(1,1) NOT NULL,

@ -520,6 +520,10 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_LOCATION (
COUNTRY VARCHAR(45) NULL, COUNTRY VARCHAR(45) NULL,
GEO_HASH VARCHAR(45) NULL, GEO_HASH VARCHAR(45) NULL,
UPDATE_TIMESTAMP BIGINT(15) NOT NULL, UPDATE_TIMESTAMP BIGINT(15) NOT NULL,
ALTITUDE DOUBLE NULL,
SPEED FLOAT NULL,
BEARING FLOAT NULL,
DISTANCE DOUBLE NULL,
PRIMARY KEY (ID), PRIMARY KEY (ID),
INDEX DM_DEVICE_LOCATION_DEVICE_idx (DEVICE_ID ASC), INDEX DM_DEVICE_LOCATION_DEVICE_idx (DEVICE_ID ASC),
INDEX DM_DEVICE_LOCATION_GEO_hashx (GEO_HASH ASC), INDEX DM_DEVICE_LOCATION_GEO_hashx (GEO_HASH ASC),
@ -537,6 +541,26 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_LOCATION (
) )
ENGINE = InnoDB; ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS DM_DEVICE_HISTORY_LAST_SEVEN_DAYS
(
ID INTEGER AUTO_INCREMENT NOT NULL,
DEVICE_ID INT NOT NULL,
DEVICE_ID_NAME VARCHAR(255) NOT NULL,
TENANT_ID INT NOT NULL,
DEVICE_TYPE_NAME VARCHAR(45) NOT NULL,
LATITUDE DOUBLE NULL,
LONGITUDE DOUBLE NULL,
SPEED FLOAT NULL,
HEADING FLOAT NULL,
TIMESTAMP BIGINT(15) NOT NULL,
GEO_HASH VARCHAR(45) NULL,
DEVICE_OWNER VARCHAR(45) NULL,
DEVICE_ALTITUDE DOUBLE NULL,
DISTANCE DOUBLE NULL,
PRIMARY KEY (ID)
)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS DM_DEVICE_DETAIL ( CREATE TABLE IF NOT EXISTS DM_DEVICE_DETAIL (
ID INT NOT NULL AUTO_INCREMENT, ID INT NOT NULL AUTO_INCREMENT,
DEVICE_ID INT NOT NULL, DEVICE_ID INT NOT NULL,

@ -842,29 +842,34 @@ WHEN (NEW.ID IS NULL)
END; END;
/ /
CREATE TABLE DM_DEVICE_LOCATION ( CREATE TABLE DM_DEVICE_LOCATION
ID NUMBER(10) NOT NULL, (
DEVICE_ID NUMBER(10) NOT NULL, ID NUMBER(10) NOT NULL,
ENROLMENT_ID NUMBER(10) NOT NULL, DEVICE_ID NUMBER(10) NOT NULL,
LATITUDE BINARY_DOUBLE NULL, TENANT_ID NUMBER(10) NOT NULL,
LONGITUDE BINARY_DOUBLE NULL, LATITUDE BINARY_DOUBLE NULL,
STREET1 VARCHAR2(255) NULL, LONGITUDE BINARY_DOUBLE NULL,
STREET2 VARCHAR2(45) NULL, STREET1 VARCHAR2(255) NULL,
CITY VARCHAR2(45) NULL, STREET2 VARCHAR2(45) NULL,
ZIP VARCHAR2(10) NULL, CITY VARCHAR2(45) NULL,
STATE VARCHAR2(45) NULL, ZIP VARCHAR2(10) NULL,
COUNTRY VARCHAR2(45) NULL, STATE VARCHAR2(45) NULL,
GEO_HASH VARCHAR(45) NULL, COUNTRY VARCHAR2(45) NULL,
UPDATE_TIMESTAMP NUMBER(19) NOT NULL, GEO_HASH VARCHAR(45) NULL,
PRIMARY KEY (ID), UPDATE_TIMESTAMP NUMBER(19) NOT NULL,
CONSTRAINT DM_DEVICE_LOCATION_DEVICE ALTITUDE BINARY_DOUBLE NULL,
FOREIGN KEY (DEVICE_ID) SPEED FLOAT NULL,
REFERENCES DM_DEVICE (ID), BEARING FLOAT NULL,
CONSTRAINT DM_DEVICE_LOCATION_DM_ENROLLMENT DISTANCE BINARY_DOUBLE NULL,
FOREIGN KEY (ENROLMENT_ID)
REFERENCES DM_ENROLMENT (ID)
)
PRIMARY KEY (ID),
CONSTRAINT DM_DEVICE_LOCATION_DEVICE
FOREIGN KEY (DEVICE_ID)
REFERENCES DM_DEVICE (ID),
CONSTRAINT DM_DEVICE_LOCATION_DM_ENROLLMENT
FOREIGN KEY (ENROLMENT_ID)
REFERENCES DM_ENROLMENT (ID)
)
/ /
CREATE INDEX DM_DEVICE_LOCATION_GEO_hashx ON DM_DEVICE_LOCATION(GEO_HASH ASC) CREATE INDEX DM_DEVICE_LOCATION_GEO_hashx ON DM_DEVICE_LOCATION(GEO_HASH ASC)
/ /
@ -880,6 +885,44 @@ WHEN (NEW.ID IS NULL)
END; END;
/ /
CREATE TABLE IF NOT EXISTS DM_DEVICE_HISTORY_LAST_SEVEN_DAYS
(
ID NUMBER(10) NOT NULL,
DEVICE_ID NUMBER(10) NOT NULL,
DEVICE_ID_NAME VARCHAR(255) NOT NULL,
ENROLMENT_ID NUMBER(10) NOT NULL,
DEVICE_TYPE_NAME VARCHAR(45) NOT NULL,
LATITUDE BINARY_DOUBLE NULL,
LONGITUDE BINARY_DOUBLE NULL,
SPEED FLOAT NULL,
HEADING FLOAT NULL,
TIMESTAMP BIGINT(15) NOT NULL,
GEO_HASH VARCHAR(45) NULL,
DEVICE_OWNER VARCHAR(45) NULL,
DEVICE_ALTITUDE BINARY_DOUBLE NULL,
DISTANCE BINARY_DOUBLE NULL,
PRIMARY KEY (ID)
)
/
CREATE INDEX DM_DEVICE_HISTORY_LAST_SEVEN_DAYS_GEO_hashx ON DM_DEVICE_HISTORY_LAST_SEVEN_DAYS (GEO_HASH ASC)
/
-- Generate ID using sequence and trigger
CREATE SEQUENCE DM_DEVICE_HISTORY_LAST_SEVEN_DAYS_seq START WITH 1 INCREMENT BY 1 NOCACHE
/
CREATE
OR
REPLACE
TRIGGER DM_DEVICE_HISTORY_LAST_SEVEN_DAYS_seq_tr
BEFORE INSERT
ON DM_DEVICE_HISTORY_LAST_SEVEN_DAYS FOR EACH ROW
WHEN (NEW.ID IS NULL)
BEGIN
SELECT DM_DEVICE_HISTORY_LAST_SEVEN_DAYS_seq.NEXTVAL INTO :NEW.ID
FROM DUAL;
END;
/
CREATE TABLE DM_DEVICE_DETAIL ( CREATE TABLE DM_DEVICE_DETAIL (
ID NUMBER(10) NOT NULL, ID NUMBER(10) NOT NULL,
DEVICE_ID NUMBER(10) NOT NULL, DEVICE_ID NUMBER(10) NOT NULL,

@ -461,6 +461,10 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_LOCATION (
COUNTRY VARCHAR(45) NULL, COUNTRY VARCHAR(45) NULL,
GEO_HASH VARCHAR(45) NULL, GEO_HASH VARCHAR(45) NULL,
UPDATE_TIMESTAMP BIGINT NOT NULL, UPDATE_TIMESTAMP BIGINT NOT NULL,
ALTITUDE DOUBLE PRECISION NULL,
SPEED FLOAT NULL,
BEARING FLOAT NULL,
DISTANCE DOUBLE PRECISION NULL,
CONSTRAINT DM_DEVICE_LOCATION_DEVICE CONSTRAINT DM_DEVICE_LOCATION_DEVICE
FOREIGN KEY (DEVICE_ID) FOREIGN KEY (DEVICE_ID)
REFERENCES DM_DEVICE (ID) REFERENCES DM_DEVICE (ID)
@ -473,6 +477,24 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_LOCATION (
ON UPDATE NO ACTION ON UPDATE NO ACTION
); );
CREATE TABLE IF NOT EXISTS DM_DEVICE_HISTORY_LAST_SEVEN_DAYS
(
ID BIGSERIAL NOT NULL PRIMARY KEY,
DEVICE_ID INT NOT NULL,
DEVICE_ID_NAME VARCHAR(255) NOT NULL,
TENANT_ID INT NOT NULL,
DEVICE_TYPE_NAME VARCHAR(45) NOT NULL,
LATITUDE DOUBLE PRECISION NULL,
LONGITUDE DOUBLE PRECISION NULL,
SPEED FLOAT NULL,
HEADING FLOAT NULL,
TIMESTAMP BIGINT(15) NOT NULL,
GEO_HASH VARCHAR(45) NULL,
DEVICE_OWNER VARCHAR(45) NULL,
DEVICE_ALTITUDE DOUBLE PRECISION NULL,
DISTANCE DOUBLE PRECISION NULL,
);
CREATE INDEX DM_DEVICE_LOCATION_GEO_hashx ON DM_DEVICE_LOCATION(GEO_HASH ASC); CREATE INDEX DM_DEVICE_LOCATION_GEO_hashx ON DM_DEVICE_LOCATION(GEO_HASH ASC);
CREATE TABLE IF NOT EXISTS DM_DEVICE_DETAIL ( CREATE TABLE IF NOT EXISTS DM_DEVICE_DETAIL (

Loading…
Cancel
Save