forked from community/device-mgt-core
Merge branch 'master' of https://github.com/wso2/carbon-device-mgt into devicetype-3.1.0
commit
3b7d4d8966
@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.wso2.carbon.device.mgt.jaxrs.service.api;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.swagger.annotations.ApiResponse;
|
||||
import io.swagger.annotations.ApiResponses;
|
||||
import io.swagger.annotations.Extension;
|
||||
import io.swagger.annotations.ExtensionProperty;
|
||||
import io.swagger.annotations.Info;
|
||||
import io.swagger.annotations.ResponseHeader;
|
||||
import io.swagger.annotations.SwaggerDefinition;
|
||||
import io.swagger.annotations.Tag;
|
||||
import org.wso2.carbon.apimgt.annotations.api.Scope;
|
||||
import org.wso2.carbon.apimgt.annotations.api.Scopes;
|
||||
import org.wso2.carbon.device.mgt.common.geo.service.Alert;
|
||||
import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
@SwaggerDefinition(
|
||||
info = @Info(
|
||||
version = "1.0.0",
|
||||
title = "",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = "name", value = "geo_services"),
|
||||
@ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/geo-services"),
|
||||
})
|
||||
}
|
||||
),
|
||||
tags = {
|
||||
@Tag(name = "device_management", description = "")
|
||||
}
|
||||
)
|
||||
@Scopes(
|
||||
scopes = {
|
||||
@Scope(
|
||||
name = "View Analytics",
|
||||
description = "",
|
||||
key = "perm:geo-service:analytics",
|
||||
permissions = {"/device-mgt/devices/owning-device/analytics"}
|
||||
)
|
||||
}
|
||||
)
|
||||
@Path("/geo-services")
|
||||
@Api(value = "Geo Service",
|
||||
description = "This carries all the resources related to the geo service functionalities.")
|
||||
public interface GeoService {
|
||||
/**
|
||||
* Retrieve Analytics for the device type
|
||||
*/
|
||||
@GET
|
||||
@Path("stats/{deviceType}/{deviceId}")
|
||||
@ApiOperation(
|
||||
consumes = "application/json",
|
||||
produces = "application/json",
|
||||
httpMethod = "GET",
|
||||
value = "Retrieve Analytics for the device type",
|
||||
notes = "",
|
||||
response = Response.class,
|
||||
tags = "Geo Service Management",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics")
|
||||
})
|
||||
}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(
|
||||
code = 200,
|
||||
message = "OK.",
|
||||
response = Response.class,
|
||||
responseHeaders = {
|
||||
@ResponseHeader(
|
||||
name = "Content-Type",
|
||||
description = "The content type of the body"),
|
||||
@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 getGeoDeviceStats(
|
||||
@ApiParam(
|
||||
name = "deviceId",
|
||||
value = "The registered device Id.",
|
||||
required = true)
|
||||
@PathParam("deviceId") String deviceId,
|
||||
@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 = "from",
|
||||
value = "Get stats from what time",
|
||||
required = true)
|
||||
@QueryParam("from") long from,
|
||||
@ApiParam(
|
||||
name = "to",
|
||||
value = "Get stats up to what time",
|
||||
required = true)
|
||||
@QueryParam("to") long to);
|
||||
|
||||
/**
|
||||
* Create Geo alerts
|
||||
*/
|
||||
@POST
|
||||
@Path("alerts/{alertType}/{deviceType}/{deviceId}")
|
||||
@ApiOperation(
|
||||
consumes = "application/json",
|
||||
produces = "application/json",
|
||||
httpMethod = "GET",
|
||||
value = "Create Geo alerts for the device",
|
||||
notes = "",
|
||||
response = Response.class,
|
||||
tags = "Geo Service Management",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics")
|
||||
})
|
||||
}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(
|
||||
code = 200,
|
||||
message = "OK.",
|
||||
response = Response.class,
|
||||
responseHeaders = {
|
||||
@ResponseHeader(
|
||||
name = "Content-Type",
|
||||
description = "The content type of the body")
|
||||
}),
|
||||
@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 createGeoAlerts(
|
||||
@ApiParam(
|
||||
name = "alert",
|
||||
value = "The alert object",
|
||||
required = true)
|
||||
@Valid Alert alert,
|
||||
@ApiParam(
|
||||
name = "deviceId",
|
||||
value = "The registered device Id.",
|
||||
required = true)
|
||||
@PathParam("deviceId") String deviceId,
|
||||
@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 = "alertType",
|
||||
value = "The alert type, such as Within, Speed, Stationary",
|
||||
required = true)
|
||||
@PathParam("alertType") String alertType);
|
||||
|
||||
/**
|
||||
* Update Geo alerts
|
||||
*/
|
||||
@PUT
|
||||
@Path("alerts/{alertType}/{deviceType}/{deviceId}")
|
||||
@ApiOperation(
|
||||
consumes = "application/json",
|
||||
produces = "application/json",
|
||||
httpMethod = "GET",
|
||||
value = "Update Geo alerts for the device",
|
||||
notes = "",
|
||||
response = Response.class,
|
||||
tags = "Geo Service Management",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics")
|
||||
})
|
||||
}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(
|
||||
code = 200,
|
||||
message = "OK.",
|
||||
response = Response.class,
|
||||
responseHeaders = {
|
||||
@ResponseHeader(
|
||||
name = "Content-Type",
|
||||
description = "The content type of the body")
|
||||
}),
|
||||
@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 updateGeoAlerts(
|
||||
@ApiParam(
|
||||
name = "alert",
|
||||
value = "The alert object",
|
||||
required = true)
|
||||
@Valid Alert alert,
|
||||
@ApiParam(
|
||||
name = "deviceId",
|
||||
value = "The registered device Id.",
|
||||
required = true)
|
||||
@PathParam("deviceId") String deviceId,
|
||||
@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 = "alertType",
|
||||
value = "The alert type, such as Within, Speed, Stationary",
|
||||
required = true)
|
||||
@PathParam("alertType") String alertType);
|
||||
|
||||
/**
|
||||
* Retrieve Geo alerts
|
||||
*/
|
||||
@GET
|
||||
@Path("alerts/{alertType}/{deviceType}/{deviceId}")
|
||||
@ApiOperation(
|
||||
consumes = "application/json",
|
||||
produces = "application/json",
|
||||
httpMethod = "GET",
|
||||
value = "Retrieve Geo alerts for the device",
|
||||
notes = "",
|
||||
response = Response.class,
|
||||
tags = "Geo Service Management",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics")
|
||||
})
|
||||
}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(
|
||||
code = 200,
|
||||
message = "OK.",
|
||||
response = Response.class,
|
||||
responseHeaders = {
|
||||
@ResponseHeader(
|
||||
name = "Content-Type",
|
||||
description = "The content type of the body"),
|
||||
@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 getGeoAlerts(
|
||||
@ApiParam(
|
||||
name = "deviceId",
|
||||
value = "The registered device Id.",
|
||||
required = true)
|
||||
@PathParam("deviceId") String deviceId,
|
||||
@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 = "alertType",
|
||||
value = "The alert type, such as Within, Speed, Stationary",
|
||||
required = true)
|
||||
@PathParam("alertType") String alertType);
|
||||
|
||||
/**
|
||||
* Retrieve Geo alerts history
|
||||
*/
|
||||
@GET
|
||||
@Path("alerts/history/{deviceType}/{deviceId}")
|
||||
@ApiOperation(
|
||||
consumes = "application/json",
|
||||
produces = "application/json",
|
||||
httpMethod = "GET",
|
||||
value = "Retrieve Geo alerts history for the device",
|
||||
notes = "",
|
||||
response = Response.class,
|
||||
tags = "Geo Service Management",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics")
|
||||
})
|
||||
}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(
|
||||
code = 200,
|
||||
message = "OK.",
|
||||
response = Response.class,
|
||||
responseHeaders = {
|
||||
@ResponseHeader(
|
||||
name = "Content-Type",
|
||||
description = "The content type of the body"),
|
||||
@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 getGeoAlertsHistory(
|
||||
@ApiParam(
|
||||
name = "deviceId",
|
||||
value = "The registered device Id.",
|
||||
required = true)
|
||||
@PathParam("deviceId") String deviceId,
|
||||
@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 = "from",
|
||||
value = "Get stats from what time",
|
||||
required = true)
|
||||
@QueryParam("from") long from,
|
||||
@ApiParam(
|
||||
name = "to",
|
||||
value = "Get stats up to what time",
|
||||
required = true)
|
||||
@QueryParam("to") long to);
|
||||
|
||||
@DELETE
|
||||
@Path("alerts/{alertType}/{deviceType}/{deviceId}")
|
||||
@ApiOperation(
|
||||
consumes = "application/json",
|
||||
produces = "application/json",
|
||||
httpMethod = "DELETE",
|
||||
value = "Create Geo alerts for the device",
|
||||
notes = "",
|
||||
response = Response.class,
|
||||
tags = "Geo Service Management",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:analytics")
|
||||
})
|
||||
}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(
|
||||
code = 200,
|
||||
message = "OK.",
|
||||
response = Response.class,
|
||||
responseHeaders = {
|
||||
@ResponseHeader(
|
||||
name = "Content-Type",
|
||||
description = "The content type of the body")
|
||||
}),
|
||||
@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 removeGeoAlerts(
|
||||
@ApiParam(
|
||||
name = "deviceId",
|
||||
value = "The registered device Id.",
|
||||
required = true)
|
||||
@PathParam("deviceId") String deviceId,
|
||||
@ApiParam(
|
||||
name = "deviceType",
|
||||
value = "The device type, such as ios, android or windows.",
|
||||
required = true)
|
||||
@PathParam("deviceType") String deviceType,
|
||||
@ApiParam(
|
||||
name = "alertType",
|
||||
value = "The alert type, such as Within, Speed, Stationary",
|
||||
required = true)
|
||||
@PathParam("alertType") String alertType,
|
||||
@ApiParam(
|
||||
name = "queryName",
|
||||
value = "The query name.",
|
||||
required = true)
|
||||
@QueryParam("queryName") String queryName);
|
||||
}
|
||||
|
@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.jaxrs.service.impl;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.analytics.api.AnalyticsDataAPI;
|
||||
import org.wso2.carbon.analytics.api.AnalyticsDataAPIUtil;
|
||||
import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDataResponse;
|
||||
import org.wso2.carbon.analytics.dataservice.commons.SearchResultEntry;
|
||||
import org.wso2.carbon.analytics.dataservice.commons.SortByField;
|
||||
import org.wso2.carbon.analytics.dataservice.commons.SortType;
|
||||
import org.wso2.carbon.analytics.datasource.commons.Record;
|
||||
import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
|
||||
import org.wso2.carbon.context.CarbonContext;
|
||||
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
|
||||
import org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices;
|
||||
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
|
||||
import org.wso2.carbon.device.mgt.common.geo.service.Alert;
|
||||
import org.wso2.carbon.device.mgt.common.geo.service.Event;
|
||||
import org.wso2.carbon.device.mgt.common.geo.service.GeoFence;
|
||||
import org.wso2.carbon.device.mgt.common.geo.service.GeoServiceException;
|
||||
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants;
|
||||
import org.wso2.carbon.device.mgt.jaxrs.service.api.GeoService;
|
||||
import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
|
||||
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
|
||||
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtUtil;
|
||||
import org.wso2.carbon.user.api.UserStoreException;
|
||||
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The api for
|
||||
*/
|
||||
public class GeoServiceImpl implements GeoService {
|
||||
|
||||
private static Log log = LogFactory.getLog(GeoServiceImpl.class);
|
||||
|
||||
@Path("stats/{deviceType}/{deviceId}")
|
||||
@GET
|
||||
@Consumes("application/json")
|
||||
@Produces("application/json")
|
||||
public Response getGeoDeviceStats(@PathParam("deviceId") String deviceId,
|
||||
@PathParam("deviceType") String deviceType,
|
||||
@QueryParam("from") long from, @QueryParam("to") long to) {
|
||||
String tableName = "IOT_PER_DEVICE_STREAM_GEO_FUSEDSPATIALEVENT";
|
||||
String fromDate = String.valueOf(from);
|
||||
String toDate = String.valueOf(to);
|
||||
String query = "id:" + deviceId + " AND type:" + deviceType;
|
||||
if (from != 0 || to != 0) {
|
||||
query += " AND timeStamp : [" + fromDate + " TO " + toDate + "]";
|
||||
}
|
||||
try {
|
||||
if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized(
|
||||
new DeviceIdentifier(deviceId, deviceType),
|
||||
DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) {
|
||||
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
|
||||
}
|
||||
List<SortByField> sortByFields = new ArrayList<>();
|
||||
SortByField sortByField = new SortByField("timeStamp", SortType.ASC);
|
||||
sortByFields.add(sortByField);
|
||||
|
||||
// this is the user who initiates the request
|
||||
String authorizedUser = MultitenantUtils.getTenantAwareUsername(
|
||||
CarbonContext.getThreadLocalCarbonContext().getUsername());
|
||||
|
||||
try {
|
||||
String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser);
|
||||
int tenantId = DeviceMgtAPIUtils.getRealmService().getTenantManager().getTenantId(tenantDomain);
|
||||
AnalyticsDataAPI analyticsDataAPI = DeviceMgtAPIUtils.getAnalyticsDataAPI();
|
||||
List<SearchResultEntry> searchResults = analyticsDataAPI.search(tenantId, tableName, query,
|
||||
0,
|
||||
100,
|
||||
sortByFields);
|
||||
List<Event> events = getEventBeans(analyticsDataAPI, tenantId, tableName, new ArrayList<String>(),
|
||||
searchResults);
|
||||
return Response.ok().entity(events).build();
|
||||
} catch (AnalyticsException | UserStoreException e) {
|
||||
log.error("Failed to perform search on table: " + tableName + " : " + e.getMessage(), e);
|
||||
throw DeviceMgtUtil.buildBadRequestException(
|
||||
Constants.ErrorMessages.STATUS_BAD_REQUEST_MESSAGE_DEFAULT);
|
||||
}
|
||||
} catch (DeviceAccessAuthorizationException e) {
|
||||
log.error(e.getErrorMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
|
||||
}
|
||||
}
|
||||
|
||||
@Path("alerts/{alertType}/{deviceType}/{deviceId}")
|
||||
@POST
|
||||
@Consumes("application/json")
|
||||
@Produces("application/json")
|
||||
public Response createGeoAlerts(Alert alert, @PathParam("deviceId") String deviceId,
|
||||
@PathParam("deviceType") String deviceType,
|
||||
@PathParam("alertType") String alertType) {
|
||||
try {
|
||||
if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized(
|
||||
new DeviceIdentifier(deviceId, deviceType),
|
||||
DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) {
|
||||
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
|
||||
}
|
||||
|
||||
// this is the user who initiates the request
|
||||
String authorizedUser = MultitenantUtils.getTenantAwareUsername(
|
||||
CarbonContext.getThreadLocalCarbonContext().getUsername()
|
||||
);
|
||||
|
||||
DeviceIdentifier identifier = new DeviceIdentifier();
|
||||
identifier.setId(deviceId);
|
||||
identifier.setType(deviceType);
|
||||
|
||||
org.wso2.carbon.device.mgt.common.geo.service.GeoService geoService = DeviceMgtAPIUtils.getGeoService();
|
||||
geoService.createGeoAlert(alert, identifier, alertType);
|
||||
return Response.ok().build();
|
||||
} catch (DeviceAccessAuthorizationException | GeoServiceException e) {
|
||||
String error = "Error occurred while creating the geo alert for " + deviceType + " with id: " + deviceId;
|
||||
log.error(error, e);
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build();
|
||||
}
|
||||
}
|
||||
|
||||
@Path("alerts/{alertType}/{deviceType}/{deviceId}")
|
||||
@PUT
|
||||
@Consumes("application/json")
|
||||
@Produces("application/json")
|
||||
public Response updateGeoAlerts(Alert alert, @PathParam("deviceId") String deviceId,
|
||||
@PathParam("deviceType") String deviceType,
|
||||
@PathParam("alertType") String alertType) {
|
||||
try {
|
||||
if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized(
|
||||
new DeviceIdentifier(deviceId, deviceType),
|
||||
DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) {
|
||||
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
|
||||
}
|
||||
|
||||
// this is the user who initiates the request
|
||||
String authorizedUser = MultitenantUtils.getTenantAwareUsername(
|
||||
CarbonContext.getThreadLocalCarbonContext().getUsername()
|
||||
);
|
||||
|
||||
DeviceIdentifier identifier = new DeviceIdentifier();
|
||||
identifier.setId(deviceId);
|
||||
identifier.setType(deviceType);
|
||||
|
||||
org.wso2.carbon.device.mgt.common.geo.service.GeoService geoService = DeviceMgtAPIUtils.getGeoService();
|
||||
geoService.updateGeoAlert(alert, identifier, alertType);
|
||||
return Response.ok().build();
|
||||
} catch (DeviceAccessAuthorizationException | GeoServiceException e) {
|
||||
String error = "Error occurred while creating the geo alert for " + deviceType + " with id: " + deviceId;
|
||||
log.error(error, e);
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build();
|
||||
}
|
||||
}
|
||||
|
||||
@Path("alerts/{alertType}/{deviceType}/{deviceId}")
|
||||
@DELETE
|
||||
@Consumes("application/json")
|
||||
@Produces("application/json")
|
||||
public Response removeGeoAlerts(@PathParam("deviceId") String deviceId,
|
||||
@PathParam("deviceType") String deviceType,
|
||||
@PathParam("alertType") String alertType,
|
||||
@QueryParam("queryName") String queryName) {
|
||||
try {
|
||||
if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized(
|
||||
new DeviceIdentifier(deviceId, deviceType),
|
||||
DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) {
|
||||
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
|
||||
}
|
||||
|
||||
// this is the user who initiates the request
|
||||
String authorizedUser = MultitenantUtils.getTenantAwareUsername(
|
||||
CarbonContext.getThreadLocalCarbonContext().getUsername()
|
||||
);
|
||||
|
||||
DeviceIdentifier identifier = new DeviceIdentifier();
|
||||
identifier.setId(deviceId);
|
||||
identifier.setType(deviceType);
|
||||
|
||||
org.wso2.carbon.device.mgt.common.geo.service.GeoService geoService = DeviceMgtAPIUtils.getGeoService();
|
||||
geoService.removeGeoAlert(alertType, identifier, queryName);
|
||||
return Response.ok().build();
|
||||
} catch (DeviceAccessAuthorizationException | GeoServiceException e) {
|
||||
String error = "Error occurred while removing the geo alert for " + deviceType + " with id: " + deviceId;
|
||||
log.error(error, e);
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build();
|
||||
}
|
||||
}
|
||||
|
||||
@Path("alerts/{alertType}/{deviceType}/{deviceId}")
|
||||
@GET
|
||||
@Consumes("application/json")
|
||||
@Produces("application/json")
|
||||
public Response getGeoAlerts(@PathParam("deviceId") String deviceId,
|
||||
@PathParam("deviceType") String deviceType,
|
||||
@PathParam("alertType") String alertType) {
|
||||
try {
|
||||
if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized(
|
||||
new DeviceIdentifier(deviceId, deviceType),
|
||||
DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) {
|
||||
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
|
||||
}
|
||||
|
||||
// this is the user who initiates the request
|
||||
String authorizedUser = MultitenantUtils.getTenantAwareUsername(
|
||||
CarbonContext.getThreadLocalCarbonContext().getUsername()
|
||||
);
|
||||
|
||||
DeviceIdentifier identifier = new DeviceIdentifier();
|
||||
identifier.setId(deviceId);
|
||||
identifier.setType(deviceType);
|
||||
|
||||
org.wso2.carbon.device.mgt.common.geo.service.GeoService geoService = DeviceMgtAPIUtils.getGeoService();
|
||||
|
||||
if (GeoServices.ALERT_TYPE_WITHIN.equals(alertType)) {
|
||||
List<GeoFence> alerts = geoService.getWithinAlerts(identifier);
|
||||
return Response.ok().entity(alerts).build();
|
||||
} else if (GeoServices.ALERT_TYPE_EXIT.equals(alertType)) {
|
||||
List<GeoFence> alerts = geoService.getExitAlerts(identifier);
|
||||
return Response.ok().entity(alerts).build();
|
||||
} else if (GeoServices.ALERT_TYPE_SPEED.equals(alertType)) {
|
||||
String result = geoService.getSpeedAlerts(identifier);
|
||||
return Response.ok().entity(result).build();
|
||||
} else if (GeoServices.ALERT_TYPE_PROXIMITY.equals(alertType)) {
|
||||
String result = geoService.getProximityAlerts(identifier);
|
||||
return Response.ok().entity(result).build();
|
||||
} else if (GeoServices.ALERT_TYPE_STATIONARY.equals(alertType)) {
|
||||
List<GeoFence> alerts = geoService.getStationaryAlerts(identifier);
|
||||
return Response.ok().entity(alerts).build();
|
||||
} else if (GeoServices.ALERT_TYPE_TRAFFIC.equals(alertType)) {
|
||||
List<GeoFence> alerts = geoService.getTrafficAlerts(identifier);
|
||||
return Response.ok().entity(alerts).build();
|
||||
}
|
||||
return null;
|
||||
} catch (DeviceAccessAuthorizationException | GeoServiceException e) {
|
||||
String error = "Error occurred while getting the geo alerts for " + deviceType + " with id: " + deviceId;
|
||||
log.error(error, e);
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build();
|
||||
}
|
||||
}
|
||||
|
||||
@Path("alerts/history/{deviceType}/{deviceId}")
|
||||
@GET
|
||||
@Consumes("application/json")
|
||||
@Produces("application/json")
|
||||
public Response getGeoAlertsHistory(@PathParam("deviceId") String deviceId,
|
||||
@PathParam("deviceType") String deviceType,
|
||||
@QueryParam("from") long from, @QueryParam("to") long to) {
|
||||
String tableName = "IOT_PER_DEVICE_STREAM_GEO_ALERTNOTIFICATIONS";
|
||||
String fromDate = String.valueOf(from);
|
||||
String toDate = String.valueOf(to);
|
||||
String query = "id:" + deviceId + " AND type:" + deviceType;
|
||||
if (from != 0 || to != 0) {
|
||||
query += " AND timeStamp : [" + fromDate + " TO " + toDate + "]";
|
||||
}
|
||||
try {
|
||||
if (!DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized(
|
||||
new DeviceIdentifier(deviceId, deviceType),
|
||||
DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) {
|
||||
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
|
||||
}
|
||||
List<SortByField> sortByFields = new ArrayList<>();
|
||||
SortByField sortByField = new SortByField("timeStamp", SortType.ASC);
|
||||
sortByFields.add(sortByField);
|
||||
|
||||
// this is the user who initiates the request
|
||||
String authorizedUser = MultitenantUtils.getTenantAwareUsername(
|
||||
CarbonContext.getThreadLocalCarbonContext().getUsername());
|
||||
|
||||
try {
|
||||
String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser);
|
||||
int tenantId = DeviceMgtAPIUtils.getRealmService().getTenantManager().getTenantId(tenantDomain);
|
||||
AnalyticsDataAPI analyticsDataAPI = DeviceMgtAPIUtils.getAnalyticsDataAPI();
|
||||
List<SearchResultEntry> searchResults = analyticsDataAPI.search(tenantId, tableName, query,
|
||||
0,
|
||||
100,
|
||||
sortByFields);
|
||||
List<Event> events = getEventBeans(analyticsDataAPI, tenantId, tableName, new ArrayList<String>(),
|
||||
searchResults);
|
||||
return Response.ok().entity(events).build();
|
||||
} catch (AnalyticsException | UserStoreException e) {
|
||||
log.error("Failed to perform search on table: " + tableName + " : " + e.getMessage(), e);
|
||||
throw DeviceMgtUtil.buildBadRequestException(
|
||||
Constants.ErrorMessages.STATUS_BAD_REQUEST_MESSAGE_DEFAULT);
|
||||
}
|
||||
} catch (DeviceAccessAuthorizationException e) {
|
||||
log.error(e.getErrorMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
|
||||
}
|
||||
}
|
||||
|
||||
private List<Event> getEventBeans(AnalyticsDataAPI analyticsDataAPI, int tenantId, String tableName,
|
||||
List<String> columns,
|
||||
List<SearchResultEntry> searchResults) throws AnalyticsException {
|
||||
List<String> ids = getIds(searchResults);
|
||||
List<String> requiredColumns = (columns == null || columns.isEmpty()) ? null : columns;
|
||||
AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, requiredColumns, ids);
|
||||
List<Record> records = AnalyticsDataAPIUtil.listRecords(analyticsDataAPI, response);
|
||||
Map<String, Event> eventBeanMap = getEventBeanKeyedWithIds(records);
|
||||
return getSortedEventBeans(eventBeanMap, searchResults);
|
||||
}
|
||||
|
||||
private List<Event> getSortedEventBeans(Map<String, Event> eventBeanMap,
|
||||
List<SearchResultEntry> searchResults) {
|
||||
List<Event> sortedRecords = new ArrayList<>();
|
||||
for (SearchResultEntry entry : searchResults) {
|
||||
sortedRecords.add(eventBeanMap.get(entry.getId()));
|
||||
}
|
||||
return sortedRecords;
|
||||
}
|
||||
|
||||
private Map<String, Event> getEventBeanKeyedWithIds(List<Record> records) {
|
||||
Map<String, Event> eventBeanMap = new HashMap<>();
|
||||
for (Record record : records) {
|
||||
Event event = getEventBean(record);
|
||||
eventBeanMap.put(event.getId(), event);
|
||||
}
|
||||
return eventBeanMap;
|
||||
}
|
||||
|
||||
private List<String> getIds(List<SearchResultEntry> searchResults) {
|
||||
List<String> ids = new ArrayList<>();
|
||||
if (searchResults != null) {
|
||||
for (SearchResultEntry resultEntry : searchResults) {
|
||||
ids.add(resultEntry.getId());
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
private static Event getEventBean(Record record) {
|
||||
Event eventBean = new Event();
|
||||
eventBean.setId(record.getId());
|
||||
eventBean.setTableName(record.getTableName());
|
||||
eventBean.setTimestamp(record.getTimestamp());
|
||||
eventBean.setValues(record.getValues());
|
||||
return eventBean;
|
||||
}
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.common.geo.service;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* The Class Alert Bean.
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "alert")
|
||||
public class Alert {
|
||||
|
||||
/**
|
||||
* The parse data.
|
||||
*/
|
||||
@XmlElement(required = true, name = "parseData")
|
||||
private String parseData;
|
||||
|
||||
/**
|
||||
* The execution plan name.
|
||||
*/
|
||||
@XmlElement(required = true, name = "executionPlan")
|
||||
private String executionPlan;
|
||||
|
||||
/**
|
||||
* The custom name.
|
||||
*/
|
||||
@XmlElement(required = false, nillable = true, name = "customName")
|
||||
private String customName;
|
||||
|
||||
/**
|
||||
* The query name.
|
||||
*/
|
||||
@XmlElementWrapper(required = true, name = "queryName")
|
||||
private String queryName;
|
||||
|
||||
/**
|
||||
* The CEP action.
|
||||
*/
|
||||
@XmlElementWrapper(required = true, name = "cepAction")
|
||||
private String cepAction;
|
||||
|
||||
/**
|
||||
* The device id.
|
||||
*/
|
||||
@XmlElementWrapper(required = true, name = "deviceId")
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* The stationery time.
|
||||
*/
|
||||
@XmlElementWrapper(required = false, nillable = true, name = "stationeryTime")
|
||||
private String stationeryTime;
|
||||
|
||||
/**
|
||||
* The fluctuation radius.
|
||||
*/
|
||||
@XmlElementWrapper(required = false, nillable = true, name = "fluctuationRadius")
|
||||
private String fluctuationRadius;
|
||||
|
||||
/**
|
||||
* The proximity distance.
|
||||
*/
|
||||
@XmlElementWrapper(required = false, nillable = true, name = "proximityDistance")
|
||||
private String proximityDistance;
|
||||
|
||||
/**
|
||||
* The proximity time.
|
||||
*/
|
||||
@XmlElementWrapper(required = false, nillable = true, name = "proximityTime")
|
||||
private String proximityTime;
|
||||
|
||||
public String getParseData() {
|
||||
return parseData;
|
||||
}
|
||||
|
||||
public void setParseData(String parseData) {
|
||||
this.parseData = parseData;
|
||||
}
|
||||
|
||||
public String getExecutionPlan() {
|
||||
return executionPlan;
|
||||
}
|
||||
|
||||
public void setExecutionPlan(String executionPlan) {
|
||||
this.executionPlan = executionPlan;
|
||||
}
|
||||
|
||||
public String getCustomName() {
|
||||
return customName;
|
||||
}
|
||||
|
||||
public void setCustomName(String customName) {
|
||||
this.customName = customName;
|
||||
}
|
||||
|
||||
public String getQueryName() {
|
||||
return queryName;
|
||||
}
|
||||
|
||||
public void setQueryName(String queryName) {
|
||||
this.queryName = queryName;
|
||||
}
|
||||
|
||||
public String getCepAction() {
|
||||
return cepAction;
|
||||
}
|
||||
|
||||
public void setCepAction(String cepAction) {
|
||||
this.cepAction = cepAction;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getStationeryTime() {
|
||||
return stationeryTime;
|
||||
}
|
||||
|
||||
public void setStationeryTime(String stationeryTime) {
|
||||
this.stationeryTime = stationeryTime;
|
||||
}
|
||||
|
||||
public String getFluctuationRadius() {
|
||||
return fluctuationRadius;
|
||||
}
|
||||
|
||||
public void setFluctuationRadius(String fluctuationRadius) {
|
||||
this.fluctuationRadius = fluctuationRadius;
|
||||
}
|
||||
|
||||
public String getProximityDistance() {
|
||||
return proximityDistance;
|
||||
}
|
||||
|
||||
public void setProximityDistance(String proximityDistance) {
|
||||
this.proximityDistance = proximityDistance;
|
||||
}
|
||||
|
||||
public String getProximityTime() {
|
||||
return proximityTime;
|
||||
}
|
||||
|
||||
public void setProximityTime(String proximityTime) {
|
||||
this.proximityTime = proximityTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"{\"queryName\" : %s,\"customName\" : %s,\"cepAction\" : %s,\"deviceId\" : %s }",
|
||||
queryName, customName, cepAction, deviceId);
|
||||
}
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.common.geo.service;
|
||||
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The Class RecordBean.
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "event")
|
||||
public class Event {
|
||||
|
||||
/** The id. */
|
||||
@XmlElement(required = false, name = "id")
|
||||
private String id;
|
||||
|
||||
/** The table name. */
|
||||
@XmlElement(required = false, name = "tableName")
|
||||
private String tableName;
|
||||
|
||||
/** The timestamp. */
|
||||
@XmlElement(required = false, nillable = true, name = "timestamp")
|
||||
private long timestamp;
|
||||
|
||||
/** The values. */
|
||||
@XmlElementWrapper(required = true, name = "values")
|
||||
private Map<String, Object> values;
|
||||
|
||||
/**
|
||||
* Sets the table name.
|
||||
* @param tableName the new table name
|
||||
*/
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the values.
|
||||
* @param values the values
|
||||
*/
|
||||
public void setValues(Map<String, Object> values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timestamp.
|
||||
* @param timestamp the new timestamp
|
||||
*/
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id.
|
||||
* @param id the new id
|
||||
*/
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
* @return the id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
/**
|
||||
* Gets the table name.
|
||||
* @return the table name
|
||||
*/
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the values.
|
||||
* @return the values
|
||||
*/
|
||||
public Map<String, Object> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value.
|
||||
* @param name
|
||||
* the name
|
||||
* @return the value
|
||||
*/
|
||||
public Object getValue(String name) {
|
||||
return this.values.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp.
|
||||
* @return the timestamp
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
List<String> valueList = new ArrayList<>();
|
||||
for (Map.Entry<String, Object> entry : values.entrySet()) {
|
||||
valueList.add(entry.getKey() + ":" + entry.getValue());
|
||||
}
|
||||
return valueList.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.common.geo.service;
|
||||
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* The Class GeoFence.
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "fence")
|
||||
public class GeoFence {
|
||||
|
||||
/** The geoJson. */
|
||||
@XmlElement(required = false, name = "geoJson")
|
||||
private String geoJson;
|
||||
|
||||
/** The queryName. */
|
||||
@XmlElement(required = false, name = "queryName")
|
||||
private String queryName;
|
||||
|
||||
/** The areaName. */
|
||||
@XmlElement(required = false, name = "areaName")
|
||||
private String areaName;
|
||||
|
||||
/** The createdTime. */
|
||||
@XmlElement(required = false, nillable = true, name = "createdTime")
|
||||
private long createdTime;
|
||||
|
||||
/** The stationaryTime. */
|
||||
@XmlElement(required = false, name = "stationaryTime")
|
||||
private String stationaryTime;
|
||||
|
||||
/** The fluctuationRadius. */
|
||||
@XmlElement(required = false, name = "fluctuationRadius")
|
||||
private String fluctuationRadius;
|
||||
|
||||
public String getGeoJson() {
|
||||
return geoJson;
|
||||
}
|
||||
|
||||
public void setGeoJson(String geoJson) {
|
||||
this.geoJson = geoJson;
|
||||
}
|
||||
|
||||
public String getQueryName() {
|
||||
return queryName;
|
||||
}
|
||||
|
||||
public void setQueryName(String queryName) {
|
||||
this.queryName = queryName;
|
||||
}
|
||||
|
||||
public String getAreaName() {
|
||||
return areaName;
|
||||
}
|
||||
|
||||
public void setAreaName(String areaName) {
|
||||
this.areaName = areaName;
|
||||
}
|
||||
|
||||
public long getCreatedTime() {
|
||||
return createdTime;
|
||||
}
|
||||
|
||||
public void setCreatedTime(long createdTime) {
|
||||
this.createdTime = createdTime;
|
||||
}
|
||||
|
||||
public void setStationaryTime(String stationaryTime) {
|
||||
this.stationaryTime = stationaryTime;
|
||||
}
|
||||
|
||||
public String getStationaryTime() {
|
||||
return stationaryTime;
|
||||
}
|
||||
|
||||
public void setFluctuationRadius(String fluctuationRadius) {
|
||||
this.fluctuationRadius = fluctuationRadius;
|
||||
}
|
||||
|
||||
public String getFluctuationRadius() {
|
||||
return fluctuationRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{\"geoJson\": " + geoJson +
|
||||
",\"queryName\": " + queryName +
|
||||
",\"areaName\":" + areaName +
|
||||
",\"createdTime\":" + createdTime +
|
||||
"}";
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* you may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.common.geo.service;
|
||||
|
||||
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This represents the Geo service functionality which should be implemented by
|
||||
* required GeoServiceManagers.
|
||||
*/
|
||||
public interface GeoService {
|
||||
|
||||
List<GeoFence> getWithinAlerts(DeviceIdentifier identifier) throws GeoServiceException;
|
||||
|
||||
List<GeoFence> getExitAlerts(DeviceIdentifier identifier) throws GeoServiceException;
|
||||
|
||||
boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType)
|
||||
throws GeoServiceException;
|
||||
|
||||
boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType)
|
||||
throws GeoServiceException;
|
||||
|
||||
boolean removeGeoAlert(String alertType, DeviceIdentifier identifier, String queryName)
|
||||
throws GeoServiceException;
|
||||
|
||||
String getSpeedAlerts(DeviceIdentifier identifier) throws GeoServiceException;
|
||||
|
||||
String getProximityAlerts(DeviceIdentifier identifier) throws GeoServiceException;
|
||||
|
||||
List<GeoFence> getStationaryAlerts(DeviceIdentifier identifier) throws GeoServiceException;
|
||||
|
||||
List<GeoFence> getTrafficAlerts(DeviceIdentifier identifier) throws GeoServiceException;
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* you may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.common.geo.service;
|
||||
|
||||
/**
|
||||
* Custom exception class of Geo Service related operations.
|
||||
*/
|
||||
public class GeoServiceException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -7151990041029070298L;
|
||||
|
||||
private String errorMessage;
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public GeoServiceException(String msg, Exception nestedEx) {
|
||||
super(msg, nestedEx);
|
||||
setErrorMessage(msg);
|
||||
}
|
||||
|
||||
public GeoServiceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
public GeoServiceException(String msg) {
|
||||
super(msg);
|
||||
setErrorMessage(msg);
|
||||
}
|
||||
|
||||
public GeoServiceException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public GeoServiceException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* you may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.config.geo.location;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* This class represents the information related to Geo Location configuration.
|
||||
*/
|
||||
@XmlRootElement(name = "GeoLocationConfiguration")
|
||||
public class GeoLocationConfiguration {
|
||||
|
||||
private boolean publishLocationOperationResponse;
|
||||
|
||||
public boolean getPublishLocationOperationResponse() {
|
||||
return publishLocationOperationResponse;
|
||||
}
|
||||
|
||||
@XmlElement(name = "PublishLocationOperationResponse", required = true)
|
||||
public void setPublishLocationOperationResponse(boolean publishLocationOperationResponse) {
|
||||
this.publishLocationOperationResponse = publishLocationOperationResponse;
|
||||
}
|
||||
}
|
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.dao.impl.group;
|
||||
|
||||
import org.wso2.carbon.device.mgt.common.Device;
|
||||
import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
|
||||
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
|
||||
import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException;
|
||||
import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory;
|
||||
import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGroupDAOImpl;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.GroupManagementDAOUtil;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class represents implementation of GroupDAO
|
||||
*/
|
||||
public class GenericGroupDAOImpl extends AbstractGroupDAOImpl {
|
||||
|
||||
@Override
|
||||
public List<DeviceGroup> getGroups(GroupPaginationRequest request, int tenantId)
|
||||
throws GroupManagementDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet resultSet = null;
|
||||
List<DeviceGroup> deviceGroupList = null;
|
||||
|
||||
String groupName = request.getGroupName();
|
||||
boolean hasGroupName = false;
|
||||
String owner = request.getOwner();
|
||||
boolean hasOwner = false;
|
||||
boolean hasLimit = request.getRowCount() != 0;
|
||||
|
||||
try {
|
||||
Connection conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER FROM DM_GROUP WHERE TENANT_ID = ?";
|
||||
if (groupName != null && !groupName.isEmpty()) {
|
||||
sql += " AND GROUP_NAME LIKE ?";
|
||||
hasGroupName = true;
|
||||
}
|
||||
if (owner != null && !owner.isEmpty()) {
|
||||
sql += " AND OWNER LIKE ?";
|
||||
hasOwner = true;
|
||||
}
|
||||
if (hasLimit) {
|
||||
sql += " LIMIT ?, ?";
|
||||
}
|
||||
|
||||
int paramIndex = 1;
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(paramIndex++, tenantId);
|
||||
if (hasGroupName) {
|
||||
stmt.setString(paramIndex++, groupName + "%");
|
||||
}
|
||||
if (hasOwner) {
|
||||
stmt.setString(paramIndex++, owner + "%");
|
||||
}
|
||||
if (hasLimit) {
|
||||
stmt.setInt(paramIndex++, request.getStartIndex());
|
||||
stmt.setInt(paramIndex, request.getRowCount());
|
||||
}
|
||||
resultSet = stmt.executeQuery();
|
||||
deviceGroupList = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e);
|
||||
} finally {
|
||||
GroupManagementDAOUtil.cleanupResources(stmt, resultSet);
|
||||
}
|
||||
return deviceGroupList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeviceGroup> getGroups(GroupPaginationRequest request, List<Integer> deviceGroupIds,
|
||||
int tenantId) throws GroupManagementDAOException {
|
||||
int deviceGroupIdsCount = deviceGroupIds.size();
|
||||
if (deviceGroupIdsCount == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet resultSet = null;
|
||||
List<DeviceGroup> deviceGroupList = null;
|
||||
|
||||
String groupName = request.getGroupName();
|
||||
boolean hasGroupName = false;
|
||||
String owner = request.getOwner();
|
||||
boolean hasOwner = false;
|
||||
boolean hasLimit = request.getRowCount() != 0;
|
||||
|
||||
try {
|
||||
Connection conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER FROM DM_GROUP WHERE TENANT_ID = ?";
|
||||
if (groupName != null && !groupName.isEmpty()) {
|
||||
sql += " AND GROUP_NAME LIKE ?";
|
||||
hasGroupName = true;
|
||||
}
|
||||
if (owner != null && !owner.isEmpty()) {
|
||||
sql += " AND OWNER LIKE ?";
|
||||
hasOwner = true;
|
||||
}
|
||||
sql += " AND ID IN (";
|
||||
for (int i = 0; i < deviceGroupIdsCount; i++) {
|
||||
sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?";
|
||||
}
|
||||
sql += ")";
|
||||
if (hasLimit) {
|
||||
sql += " LIMIT ?, ?";
|
||||
}
|
||||
|
||||
int paramIndex = 1;
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(paramIndex++, tenantId);
|
||||
if (hasGroupName) {
|
||||
stmt.setString(paramIndex++, groupName + "%");
|
||||
}
|
||||
if (hasOwner) {
|
||||
stmt.setString(paramIndex++, owner + "%");
|
||||
}
|
||||
for (Integer deviceGroupId : deviceGroupIds) {
|
||||
stmt.setInt(paramIndex++, deviceGroupId);
|
||||
}
|
||||
if (hasLimit) {
|
||||
stmt.setInt(paramIndex++, request.getStartIndex());
|
||||
stmt.setInt(paramIndex, request.getRowCount());
|
||||
}
|
||||
resultSet = stmt.executeQuery();
|
||||
deviceGroupList = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e);
|
||||
} finally {
|
||||
GroupManagementDAOUtil.cleanupResources(stmt, resultSet);
|
||||
}
|
||||
return deviceGroupList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Device> getDevices(int groupId, int startIndex, int rowCount, int tenantId)
|
||||
throws GroupManagementDAOException {
|
||||
Connection conn;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
List<Device> devices = null;
|
||||
try {
|
||||
conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT d1.DEVICE_ID, d1.DESCRIPTION, d1.NAME AS DEVICE_NAME, d1.DEVICE_TYPE, " +
|
||||
"d1.DEVICE_IDENTIFICATION, e.OWNER, e.OWNERSHIP, e.STATUS, e.DATE_OF_LAST_UPDATE, " +
|
||||
"e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, " +
|
||||
"(SELECT gd.DEVICE_ID, gd.DESCRIPTION, gd.NAME, gd.DEVICE_IDENTIFICATION, t.NAME AS DEVICE_TYPE " +
|
||||
"FROM " +
|
||||
"(SELECT d.ID AS DEVICE_ID, d.DESCRIPTION, d.NAME, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID FROM" +
|
||||
" DM_DEVICE d, (" +
|
||||
"SELECT dgm.DEVICE_ID FROM DM_DEVICE_GROUP_MAP dgm WHERE dgm.GROUP_ID = ?) dgm1 " +
|
||||
"WHERE d.ID = dgm1.DEVICE_ID AND d.TENANT_ID = ?) gd, DM_DEVICE_TYPE t " +
|
||||
"WHERE gd.DEVICE_TYPE_ID = t.ID) d1 WHERE d1.DEVICE_ID = e.DEVICE_ID AND TENANT_ID = ? LIMIT ? , ?";
|
||||
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, groupId);
|
||||
stmt.setInt(2, tenantId);
|
||||
stmt.setInt(3, tenantId);
|
||||
//noinspection JpaQueryApiInspection
|
||||
stmt.setInt(4, startIndex);
|
||||
//noinspection JpaQueryApiInspection
|
||||
stmt.setInt(5, rowCount);
|
||||
rs = stmt.executeQuery();
|
||||
devices = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
Device device = DeviceManagementDAOUtil.loadDevice(rs);
|
||||
devices.add(device);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while retrieving information of all " +
|
||||
"registered devices", e);
|
||||
} finally {
|
||||
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
}
|
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.dao.impl.group;
|
||||
|
||||
import org.wso2.carbon.device.mgt.common.Device;
|
||||
import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
|
||||
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
|
||||
import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException;
|
||||
import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory;
|
||||
import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGroupDAOImpl;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.GroupManagementDAOUtil;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class represents implementation of GroupDAO
|
||||
*/
|
||||
public class OracleGroupDAOImpl extends AbstractGroupDAOImpl {
|
||||
|
||||
@Override
|
||||
public List<DeviceGroup> getGroups(GroupPaginationRequest request, int tenantId)
|
||||
throws GroupManagementDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet resultSet = null;
|
||||
List<DeviceGroup> deviceGroupList = null;
|
||||
|
||||
String groupName = request.getGroupName();
|
||||
boolean hasGroupName = false;
|
||||
String owner = request.getOwner();
|
||||
boolean hasOwner = false;
|
||||
boolean hasLimit = request.getRowCount() != 0;
|
||||
|
||||
try {
|
||||
Connection conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER FROM DM_GROUP WHERE TENANT_ID = ?";
|
||||
if (groupName != null && !groupName.isEmpty()) {
|
||||
sql += " AND GROUP_NAME LIKE ?";
|
||||
hasGroupName = true;
|
||||
}
|
||||
if (owner != null && !owner.isEmpty()) {
|
||||
sql += " AND OWNER LIKE ?";
|
||||
hasOwner = true;
|
||||
}
|
||||
if (hasLimit) {
|
||||
sql += " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
|
||||
}
|
||||
|
||||
int paramIndex = 1;
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(paramIndex++, tenantId);
|
||||
if (hasGroupName) {
|
||||
stmt.setString(paramIndex++, groupName + "%");
|
||||
}
|
||||
if (hasOwner) {
|
||||
stmt.setString(paramIndex++, owner + "%");
|
||||
}
|
||||
if (hasLimit) {
|
||||
stmt.setInt(paramIndex++, request.getStartIndex());
|
||||
stmt.setInt(paramIndex, request.getRowCount());
|
||||
}
|
||||
resultSet = stmt.executeQuery();
|
||||
deviceGroupList = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e);
|
||||
} finally {
|
||||
GroupManagementDAOUtil.cleanupResources(stmt, resultSet);
|
||||
}
|
||||
return deviceGroupList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeviceGroup> getGroups(GroupPaginationRequest request, List<Integer> deviceGroupIds,
|
||||
int tenantId) throws GroupManagementDAOException {
|
||||
int deviceGroupIdsCount = deviceGroupIds.size();
|
||||
if (deviceGroupIdsCount == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet resultSet = null;
|
||||
List<DeviceGroup> deviceGroupList = null;
|
||||
|
||||
String groupName = request.getGroupName();
|
||||
boolean hasGroupName = false;
|
||||
String owner = request.getOwner();
|
||||
boolean hasOwner = false;
|
||||
boolean hasLimit = request.getRowCount() != 0;
|
||||
|
||||
try {
|
||||
Connection conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER FROM DM_GROUP WHERE TENANT_ID = ?";
|
||||
if (groupName != null && !groupName.isEmpty()) {
|
||||
sql += " AND GROUP_NAME LIKE ?";
|
||||
hasGroupName = true;
|
||||
}
|
||||
if (owner != null && !owner.isEmpty()) {
|
||||
sql += " AND OWNER LIKE ?";
|
||||
hasOwner = true;
|
||||
}
|
||||
sql += " AND ID IN (";
|
||||
for (int i = 0; i < deviceGroupIdsCount; i++) {
|
||||
sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?";
|
||||
}
|
||||
sql += ")";
|
||||
if (hasLimit) {
|
||||
sql += " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
|
||||
}
|
||||
|
||||
int paramIndex = 1;
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(paramIndex++, tenantId);
|
||||
if (hasGroupName) {
|
||||
stmt.setString(paramIndex++, groupName + "%");
|
||||
}
|
||||
if (hasOwner) {
|
||||
stmt.setString(paramIndex++, owner + "%");
|
||||
}
|
||||
for (Integer deviceGroupId : deviceGroupIds) {
|
||||
stmt.setInt(paramIndex++, deviceGroupId);
|
||||
}
|
||||
if (hasLimit) {
|
||||
stmt.setInt(paramIndex++, request.getStartIndex());
|
||||
stmt.setInt(paramIndex, request.getRowCount());
|
||||
}
|
||||
resultSet = stmt.executeQuery();
|
||||
deviceGroupList = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e);
|
||||
} finally {
|
||||
GroupManagementDAOUtil.cleanupResources(stmt, resultSet);
|
||||
}
|
||||
return deviceGroupList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Device> getDevices(int groupId, int startIndex, int rowCount, int tenantId)
|
||||
throws GroupManagementDAOException {
|
||||
Connection conn;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
List<Device> devices = null;
|
||||
try {
|
||||
conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT d1.DEVICE_ID, d1.DESCRIPTION, d1.NAME AS DEVICE_NAME, d1.DEVICE_TYPE, " +
|
||||
"d1.DEVICE_IDENTIFICATION, e.OWNER, e.OWNERSHIP, e.STATUS, e.DATE_OF_LAST_UPDATE, " +
|
||||
"e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, " +
|
||||
"(SELECT gd.DEVICE_ID, gd.DESCRIPTION, gd.NAME, gd.DEVICE_IDENTIFICATION, t.NAME AS DEVICE_TYPE " +
|
||||
"FROM " +
|
||||
"(SELECT d.ID AS DEVICE_ID, d.DESCRIPTION, d.NAME, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID FROM" +
|
||||
" DM_DEVICE d, (" +
|
||||
"SELECT dgm.DEVICE_ID FROM DM_DEVICE_GROUP_MAP dgm WHERE dgm.GROUP_ID = ?) dgm1 " +
|
||||
"WHERE d.ID = dgm1.DEVICE_ID AND d.TENANT_ID = ?) gd, DM_DEVICE_TYPE t " +
|
||||
"WHERE gd.DEVICE_TYPE_ID = t.ID) d1 WHERE d1.DEVICE_ID = e.DEVICE_ID AND TENANT_ID = ? OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
|
||||
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, groupId);
|
||||
stmt.setInt(2, tenantId);
|
||||
stmt.setInt(3, tenantId);
|
||||
//noinspection JpaQueryApiInspection
|
||||
stmt.setInt(4, startIndex);
|
||||
//noinspection JpaQueryApiInspection
|
||||
stmt.setInt(5, rowCount);
|
||||
rs = stmt.executeQuery();
|
||||
devices = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
Device device = DeviceManagementDAOUtil.loadDevice(rs);
|
||||
devices.add(device);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while retrieving information of all " +
|
||||
"registered devices", e);
|
||||
} finally {
|
||||
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
}
|
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.dao.impl.group;
|
||||
|
||||
import org.wso2.carbon.device.mgt.common.Device;
|
||||
import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
|
||||
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
|
||||
import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException;
|
||||
import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory;
|
||||
import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGroupDAOImpl;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.GroupManagementDAOUtil;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class represents implementation of GroupDAO
|
||||
*/
|
||||
public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl {
|
||||
|
||||
@Override
|
||||
public List<DeviceGroup> getGroups(GroupPaginationRequest request, int tenantId)
|
||||
throws GroupManagementDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet resultSet = null;
|
||||
List<DeviceGroup> deviceGroupList = null;
|
||||
|
||||
String groupName = request.getGroupName();
|
||||
boolean hasGroupName = false;
|
||||
String owner = request.getOwner();
|
||||
boolean hasOwner = false;
|
||||
boolean hasLimit = request.getRowCount() != 0;
|
||||
|
||||
try {
|
||||
Connection conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER FROM DM_GROUP WHERE TENANT_ID = ?";
|
||||
if (groupName != null && !groupName.isEmpty()) {
|
||||
sql += " AND GROUP_NAME LIKE ?";
|
||||
hasGroupName = true;
|
||||
}
|
||||
if (owner != null && !owner.isEmpty()) {
|
||||
sql += " AND OWNER LIKE ?";
|
||||
hasOwner = true;
|
||||
}
|
||||
if (hasLimit) {
|
||||
sql += " LIMIT ? OFFSET ?";
|
||||
}
|
||||
|
||||
int paramIndex = 1;
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(paramIndex++, tenantId);
|
||||
if (hasGroupName) {
|
||||
stmt.setString(paramIndex++, groupName + "%");
|
||||
}
|
||||
if (hasOwner) {
|
||||
stmt.setString(paramIndex++, owner + "%");
|
||||
}
|
||||
if (hasLimit) {
|
||||
stmt.setInt(paramIndex++, request.getRowCount());
|
||||
stmt.setInt(paramIndex, request.getStartIndex());
|
||||
}
|
||||
resultSet = stmt.executeQuery();
|
||||
deviceGroupList = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e);
|
||||
} finally {
|
||||
GroupManagementDAOUtil.cleanupResources(stmt, resultSet);
|
||||
}
|
||||
return deviceGroupList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeviceGroup> getGroups(GroupPaginationRequest request, List<Integer> deviceGroupIds,
|
||||
int tenantId) throws GroupManagementDAOException {
|
||||
int deviceGroupIdsCount = deviceGroupIds.size();
|
||||
if (deviceGroupIdsCount == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet resultSet = null;
|
||||
List<DeviceGroup> deviceGroupList = null;
|
||||
|
||||
String groupName = request.getGroupName();
|
||||
boolean hasGroupName = false;
|
||||
String owner = request.getOwner();
|
||||
boolean hasOwner = false;
|
||||
boolean hasLimit = request.getRowCount() != 0;
|
||||
|
||||
try {
|
||||
Connection conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER FROM DM_GROUP WHERE TENANT_ID = ?";
|
||||
if (groupName != null && !groupName.isEmpty()) {
|
||||
sql += " AND GROUP_NAME LIKE ?";
|
||||
hasGroupName = true;
|
||||
}
|
||||
if (owner != null && !owner.isEmpty()) {
|
||||
sql += " AND OWNER LIKE ?";
|
||||
hasOwner = true;
|
||||
}
|
||||
sql += " AND ID IN (";
|
||||
for (int i = 0; i < deviceGroupIdsCount; i++) {
|
||||
sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?";
|
||||
}
|
||||
sql += ")";
|
||||
if (hasLimit) {
|
||||
sql += " LIMIT ? OFFSET ?";
|
||||
}
|
||||
|
||||
int paramIndex = 1;
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(paramIndex++, tenantId);
|
||||
if (hasGroupName) {
|
||||
stmt.setString(paramIndex++, groupName + "%");
|
||||
}
|
||||
if (hasOwner) {
|
||||
stmt.setString(paramIndex++, owner + "%");
|
||||
}
|
||||
for (Integer deviceGroupId : deviceGroupIds) {
|
||||
stmt.setInt(paramIndex++, deviceGroupId);
|
||||
}
|
||||
if (hasLimit) {
|
||||
stmt.setInt(paramIndex++, request.getRowCount());
|
||||
stmt.setInt(paramIndex, request.getStartIndex());
|
||||
}
|
||||
resultSet = stmt.executeQuery();
|
||||
deviceGroupList = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e);
|
||||
} finally {
|
||||
GroupManagementDAOUtil.cleanupResources(stmt, resultSet);
|
||||
}
|
||||
return deviceGroupList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Device> getDevices(int groupId, int startIndex, int rowCount, int tenantId)
|
||||
throws GroupManagementDAOException {
|
||||
Connection conn;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
List<Device> devices = null;
|
||||
try {
|
||||
conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT d1.DEVICE_ID, d1.DESCRIPTION, d1.NAME AS DEVICE_NAME, d1.DEVICE_TYPE, " +
|
||||
"d1.DEVICE_IDENTIFICATION, e.OWNER, e.OWNERSHIP, e.STATUS, e.DATE_OF_LAST_UPDATE, " +
|
||||
"e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, " +
|
||||
"(SELECT gd.DEVICE_ID, gd.DESCRIPTION, gd.NAME, gd.DEVICE_IDENTIFICATION, t.NAME AS DEVICE_TYPE " +
|
||||
"FROM " +
|
||||
"(SELECT d.ID AS DEVICE_ID, d.DESCRIPTION, d.NAME, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID FROM" +
|
||||
" DM_DEVICE d, (" +
|
||||
"SELECT dgm.DEVICE_ID FROM DM_DEVICE_GROUP_MAP dgm WHERE dgm.GROUP_ID = ?) dgm1 " +
|
||||
"WHERE d.ID = dgm1.DEVICE_ID AND d.TENANT_ID = ?) gd, DM_DEVICE_TYPE t " +
|
||||
"WHERE gd.DEVICE_TYPE_ID = t.ID) d1 WHERE d1.DEVICE_ID = e.DEVICE_ID AND TENANT_ID = ? LIMIT ? OFFSET ?";
|
||||
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, groupId);
|
||||
stmt.setInt(2, tenantId);
|
||||
stmt.setInt(3, tenantId);
|
||||
//noinspection JpaQueryApiInspection
|
||||
stmt.setInt(4, rowCount);
|
||||
//noinspection JpaQueryApiInspection
|
||||
stmt.setInt(5, startIndex);
|
||||
rs = stmt.executeQuery();
|
||||
devices = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
Device device = DeviceManagementDAOUtil.loadDevice(rs);
|
||||
devices.add(device);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while retrieving information of all " +
|
||||
"registered devices", e);
|
||||
} finally {
|
||||
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
}
|
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.dao.impl.group;
|
||||
|
||||
import org.wso2.carbon.device.mgt.common.Device;
|
||||
import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
|
||||
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
|
||||
import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException;
|
||||
import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory;
|
||||
import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGroupDAOImpl;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.GroupManagementDAOUtil;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class represents implementation of GroupDAO
|
||||
*/
|
||||
public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl {
|
||||
|
||||
@Override
|
||||
public List<DeviceGroup> getGroups(GroupPaginationRequest request, int tenantId)
|
||||
throws GroupManagementDAOException {
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet resultSet = null;
|
||||
List<DeviceGroup> deviceGroupList = null;
|
||||
|
||||
String groupName = request.getGroupName();
|
||||
boolean hasGroupName = false;
|
||||
String owner = request.getOwner();
|
||||
boolean hasOwner = false;
|
||||
boolean hasLimit = request.getRowCount() != 0;
|
||||
|
||||
try {
|
||||
Connection conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER FROM DM_GROUP WHERE TENANT_ID = ?";
|
||||
if (groupName != null && !groupName.isEmpty()) {
|
||||
sql += " AND GROUP_NAME LIKE ?";
|
||||
hasGroupName = true;
|
||||
}
|
||||
if (owner != null && !owner.isEmpty()) {
|
||||
sql += " AND OWNER LIKE ?";
|
||||
hasOwner = true;
|
||||
}
|
||||
if (hasLimit) {
|
||||
sql += " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
|
||||
}
|
||||
|
||||
int paramIndex = 1;
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(paramIndex++, tenantId);
|
||||
if (hasGroupName) {
|
||||
stmt.setString(paramIndex++, groupName + "%");
|
||||
}
|
||||
if (hasOwner) {
|
||||
stmt.setString(paramIndex++, owner + "%");
|
||||
}
|
||||
if (hasLimit) {
|
||||
stmt.setInt(paramIndex++, request.getStartIndex());
|
||||
stmt.setInt(paramIndex, request.getRowCount());
|
||||
}
|
||||
resultSet = stmt.executeQuery();
|
||||
deviceGroupList = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e);
|
||||
} finally {
|
||||
GroupManagementDAOUtil.cleanupResources(stmt, resultSet);
|
||||
}
|
||||
return deviceGroupList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeviceGroup> getGroups(GroupPaginationRequest request, List<Integer> deviceGroupIds,
|
||||
int tenantId) throws GroupManagementDAOException {
|
||||
int deviceGroupIdsCount = deviceGroupIds.size();
|
||||
if (deviceGroupIdsCount == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet resultSet = null;
|
||||
List<DeviceGroup> deviceGroupList = null;
|
||||
|
||||
String groupName = request.getGroupName();
|
||||
boolean hasGroupName = false;
|
||||
String owner = request.getOwner();
|
||||
boolean hasOwner = false;
|
||||
boolean hasLimit = request.getRowCount() != 0;
|
||||
|
||||
try {
|
||||
Connection conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER FROM DM_GROUP WHERE TENANT_ID = ?";
|
||||
if (groupName != null && !groupName.isEmpty()) {
|
||||
sql += " AND GROUP_NAME LIKE ?";
|
||||
hasGroupName = true;
|
||||
}
|
||||
if (owner != null && !owner.isEmpty()) {
|
||||
sql += " AND OWNER LIKE ?";
|
||||
hasOwner = true;
|
||||
}
|
||||
sql += " AND ID IN (";
|
||||
for (int i = 0; i < deviceGroupIdsCount; i++) {
|
||||
sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?";
|
||||
}
|
||||
sql += ")";
|
||||
if (hasLimit) {
|
||||
sql += " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
|
||||
}
|
||||
|
||||
int paramIndex = 1;
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(paramIndex++, tenantId);
|
||||
if (hasGroupName) {
|
||||
stmt.setString(paramIndex++, groupName + "%");
|
||||
}
|
||||
if (hasOwner) {
|
||||
stmt.setString(paramIndex++, owner + "%");
|
||||
}
|
||||
for (Integer deviceGroupId : deviceGroupIds) {
|
||||
stmt.setInt(paramIndex++, deviceGroupId);
|
||||
}
|
||||
if (hasLimit) {
|
||||
stmt.setInt(paramIndex++, request.getStartIndex());
|
||||
stmt.setInt(paramIndex, request.getRowCount());
|
||||
}
|
||||
resultSet = stmt.executeQuery();
|
||||
deviceGroupList = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e);
|
||||
} finally {
|
||||
GroupManagementDAOUtil.cleanupResources(stmt, resultSet);
|
||||
}
|
||||
return deviceGroupList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Device> getDevices(int groupId, int startIndex, int rowCount, int tenantId)
|
||||
throws GroupManagementDAOException {
|
||||
Connection conn;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
List<Device> devices = null;
|
||||
try {
|
||||
conn = GroupManagementDAOFactory.getConnection();
|
||||
String sql = "SELECT d1.DEVICE_ID, d1.DESCRIPTION, d1.NAME AS DEVICE_NAME, d1.DEVICE_TYPE, " +
|
||||
"d1.DEVICE_IDENTIFICATION, e.OWNER, e.OWNERSHIP, e.STATUS, e.DATE_OF_LAST_UPDATE, " +
|
||||
"e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, " +
|
||||
"(SELECT gd.DEVICE_ID, gd.DESCRIPTION, gd.NAME, gd.DEVICE_IDENTIFICATION, t.NAME AS DEVICE_TYPE " +
|
||||
"FROM " +
|
||||
"(SELECT d.ID AS DEVICE_ID, d.DESCRIPTION, d.NAME, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID FROM" +
|
||||
" DM_DEVICE d, (" +
|
||||
"SELECT dgm.DEVICE_ID FROM DM_DEVICE_GROUP_MAP dgm WHERE dgm.GROUP_ID = ?) dgm1 " +
|
||||
"WHERE d.ID = dgm1.DEVICE_ID AND d.TENANT_ID = ?) gd, DM_DEVICE_TYPE t " +
|
||||
"WHERE gd.DEVICE_TYPE_ID = t.ID) d1 WHERE d1.DEVICE_ID = e.DEVICE_ID AND TENANT_ID = ? OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
|
||||
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, groupId);
|
||||
stmt.setInt(2, tenantId);
|
||||
stmt.setInt(3, tenantId);
|
||||
//noinspection JpaQueryApiInspection
|
||||
stmt.setInt(4, startIndex);
|
||||
//noinspection JpaQueryApiInspection
|
||||
stmt.setInt(5, rowCount);
|
||||
rs = stmt.executeQuery();
|
||||
devices = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
Device device = DeviceManagementDAOUtil.loadDevice(rs);
|
||||
devices.add(device);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new GroupManagementDAOException("Error occurred while retrieving information of all " +
|
||||
"registered devices", e);
|
||||
} finally {
|
||||
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
}
|
@ -0,0 +1,728 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* you may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.core.geo.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.apache.axis2.AxisFault;
|
||||
import org.apache.axis2.client.Options;
|
||||
import org.apache.axis2.client.Stub;
|
||||
import org.apache.axis2.java.security.SSLProtocolSocketFactory;
|
||||
import org.apache.axis2.transport.http.HTTPConstants;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.httpclient.Header;
|
||||
import org.apache.commons.httpclient.protocol.Protocol;
|
||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.base.ServerConfiguration;
|
||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import org.wso2.carbon.core.util.Utils;
|
||||
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
|
||||
import org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices;
|
||||
import org.wso2.carbon.device.mgt.common.geo.service.Alert;
|
||||
import org.wso2.carbon.device.mgt.common.geo.service.GeoFence;
|
||||
import org.wso2.carbon.device.mgt.common.geo.service.GeoService;
|
||||
import org.wso2.carbon.device.mgt.common.geo.service.GeoServiceException;
|
||||
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
|
||||
import org.wso2.carbon.event.processor.stub.EventProcessorAdminServiceStub;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
|
||||
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
|
||||
import org.wso2.carbon.registry.api.Registry;
|
||||
import org.wso2.carbon.registry.api.RegistryException;
|
||||
import org.wso2.carbon.registry.api.Resource;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices.DAS_PORT;
|
||||
import static org.wso2.carbon.device.mgt.common.DeviceManagementConstants.GeoServices.DEFAULT_HTTP_PROTOCOL;
|
||||
|
||||
/**
|
||||
* This class will read events, set alerts, read alerts related to geo-fencing and it will
|
||||
* use Registry as the persistence storage.
|
||||
*/
|
||||
public class GeoServcieManagerImpl implements GeoService {
|
||||
|
||||
private static Log log = LogFactory.getLog(GeoServcieManagerImpl.class);
|
||||
|
||||
/**
|
||||
* required soap header for authorization
|
||||
*/
|
||||
private static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
/**
|
||||
* required soap header value for mutualSSL
|
||||
*/
|
||||
private static final String AUTHORIZATION_HEADER_VALUE = "Bearer";
|
||||
/**
|
||||
* Default keystore type of the client
|
||||
*/
|
||||
private static final String KEY_STORE_TYPE = "JKS";
|
||||
/**
|
||||
* Default truststore type of the client
|
||||
*/
|
||||
private static final String TRUST_STORE_TYPE = "JKS";
|
||||
/**
|
||||
* Default keymanager type of the client
|
||||
*/
|
||||
private static final String KEY_MANAGER_TYPE = "SunX509"; //Default Key Manager Type
|
||||
/**
|
||||
* Default trustmanager type of the client
|
||||
*/
|
||||
private static final String TRUST_MANAGER_TYPE = "SunX509"; //Default Trust Manager Type
|
||||
|
||||
private static final String SSLV3 = "SSLv3";
|
||||
|
||||
@Override
|
||||
public List<GeoFence> getWithinAlerts(DeviceIdentifier identifier) throws GeoServiceException {
|
||||
|
||||
Registry registry = getGovernanceRegistry();
|
||||
String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS +
|
||||
GeoServices.ALERT_TYPE_WITHIN + "/" + identifier.getId() + "/";
|
||||
Resource resource;
|
||||
try {
|
||||
resource = registry.get(registryPath);
|
||||
} catch (RegistryException e) {
|
||||
log.error("Error while reading the registry path: " + registryPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
List<GeoFence> fences = new ArrayList<>();
|
||||
if (resource != null) {
|
||||
Object contentObj = resource.getContent();
|
||||
if (contentObj instanceof String[]) {
|
||||
String[] content = (String[]) contentObj;
|
||||
for (String res : content) {
|
||||
Resource childRes = registry.get(res);
|
||||
Properties props = childRes.getProperties();
|
||||
|
||||
GeoFence geoFence = new GeoFence();
|
||||
|
||||
InputStream inputStream = childRes.getContentStream();
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(inputStream, writer, "UTF-8");
|
||||
geoFence.setGeoJson(writer.toString());
|
||||
|
||||
List queryNameObj = (List) props.get(GeoServices.QUERY_NAME);
|
||||
geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null);
|
||||
List areaNameObj = (List) props.get(GeoServices.AREA_NAME);
|
||||
geoFence.setAreaName(areaNameObj != null ? areaNameObj.get(0).toString() : null);
|
||||
geoFence.setCreatedTime(childRes.getCreatedTime().getTime());
|
||||
fences.add(geoFence);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fences;
|
||||
} catch (RegistryException | IOException e) {
|
||||
throw new GeoServiceException(
|
||||
"Error occurred while getting the geo alerts for " + identifier.getType() + " with id: " +
|
||||
identifier.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GeoFence> getExitAlerts(DeviceIdentifier identifier) throws GeoServiceException {
|
||||
|
||||
Registry registry = getGovernanceRegistry();
|
||||
String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS +
|
||||
GeoServices.ALERT_TYPE_EXIT + "/" + identifier.getId() + "/";
|
||||
Resource resource;
|
||||
try {
|
||||
resource = registry.get(registryPath);
|
||||
} catch (RegistryException e) {
|
||||
log.error("Error while reading the registry path: " + registryPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
List<GeoFence> fences = new ArrayList<>();
|
||||
if (resource != null) {
|
||||
Object contentObj = resource.getContent();
|
||||
if (contentObj instanceof String[]) {
|
||||
String[] content = (String[]) contentObj;
|
||||
for (String res : content) {
|
||||
Resource childRes = registry.get(res);
|
||||
Properties props = childRes.getProperties();
|
||||
|
||||
GeoFence geoFence = new GeoFence();
|
||||
|
||||
InputStream inputStream = childRes.getContentStream();
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(inputStream, writer, "UTF-8");
|
||||
geoFence.setGeoJson(writer.toString());
|
||||
|
||||
List queryNameObj = (List) props.get(GeoServices.QUERY_NAME);
|
||||
geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null);
|
||||
List areaNameObj = (List) props.get(GeoServices.AREA_NAME);
|
||||
geoFence.setAreaName(areaNameObj != null ? areaNameObj.get(0).toString() : null);
|
||||
geoFence.setCreatedTime(childRes.getCreatedTime().getTime());
|
||||
fences.add(geoFence);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fences;
|
||||
} catch (RegistryException | IOException e) {
|
||||
throw new GeoServiceException(
|
||||
"Error occurred while getting the geo alerts for " + identifier.getType() + " with id: " +
|
||||
identifier.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType)
|
||||
throws GeoServiceException {
|
||||
return saveGeoAlert(alert, identifier, alertType, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType)
|
||||
throws GeoServiceException {
|
||||
return saveGeoAlert(alert, identifier, alertType, true);
|
||||
}
|
||||
|
||||
public boolean saveGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType, boolean isUpdate)
|
||||
throws GeoServiceException {
|
||||
|
||||
Type type = new TypeToken<Map<String, String>>() {
|
||||
}.getType();
|
||||
Gson gson = new Gson();
|
||||
Map<String, String> parseMap = gson.fromJson(alert.getParseData(), type);
|
||||
|
||||
Map<String, String> options = new HashMap<>();
|
||||
Object content = null;
|
||||
|
||||
if (GeoServices.ALERT_TYPE_WITHIN.equals(alertType)) {
|
||||
options.put(GeoServices.QUERY_NAME, alert.getQueryName());
|
||||
options.put(GeoServices.AREA_NAME, alert.getCustomName());
|
||||
content = parseMap.get(GeoServices.GEO_FENCE_GEO_JSON);
|
||||
|
||||
} else if (GeoServices.ALERT_TYPE_EXIT.equals(alertType)) {
|
||||
options.put(GeoServices.QUERY_NAME, alert.getQueryName());
|
||||
options.put(GeoServices.AREA_NAME, alert.getCustomName());
|
||||
content = parseMap.get(GeoServices.GEO_FENCE_GEO_JSON);
|
||||
|
||||
} else if (GeoServices.ALERT_TYPE_SPEED.equals(alertType)) {
|
||||
content = parseMap.get(GeoServices.SPEED_ALERT_VALUE);
|
||||
|
||||
} else if (GeoServices.ALERT_TYPE_PROXIMITY.equals(alertType)) {
|
||||
options.put(GeoServices.PROXIMITY_DISTANCE, alert.getProximityDistance());
|
||||
options.put(GeoServices.PROXIMITY_TIME, alert.getProximityTime());
|
||||
content = alert.getParseData();
|
||||
|
||||
} else if (GeoServices.ALERT_TYPE_STATIONARY.equals(alertType)) {
|
||||
options.put(GeoServices.QUERY_NAME, alert.getQueryName());
|
||||
options.put(GeoServices.AREA_NAME, alert.getCustomName());
|
||||
options.put(GeoServices.STATIONARY_TIME, alert.getStationeryTime());
|
||||
options.put(GeoServices.FLUCTUATION_RADIUS, alert.getFluctuationRadius());
|
||||
content = alert.getParseData();
|
||||
|
||||
} else if (GeoServices.ALERT_TYPE_TRAFFIC.equals(alertType)) {
|
||||
content = parseMap.get(GeoServices.GEO_FENCE_GEO_JSON);
|
||||
} else {
|
||||
throw new GeoServiceException(
|
||||
"Unrecognized execution plan type: " + alertType + " while creating geo alert");
|
||||
}
|
||||
|
||||
//persist alert in registry
|
||||
updateRegistry(getRegistryPath(alertType, identifier, alert.getQueryName()), identifier, content,
|
||||
options);
|
||||
|
||||
//deploy alert into event processor
|
||||
EventProcessorAdminServiceStub eventprocessorStub = null;
|
||||
String action = (isUpdate ? "updating" : "creating");
|
||||
try {
|
||||
eventprocessorStub = getEventProcessorAdminServiceStub();
|
||||
String parsedTemplate = parseTemplate(alertType, parseMap);
|
||||
String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate);
|
||||
if (validationResponse.equals("success")) {
|
||||
if (isUpdate) {
|
||||
String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName(),
|
||||
identifier.getId());
|
||||
eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName);
|
||||
} else {
|
||||
eventprocessorStub.deployExecutionPlan(parsedTemplate);
|
||||
}
|
||||
} else {
|
||||
if (validationResponse.startsWith(
|
||||
"'within' is neither a function extension nor an aggregated attribute extension"
|
||||
)) {
|
||||
log.error("GPL Siddhi Geo Extension is not configured. Please execute maven script " +
|
||||
"`siddhi-geo-extention-deployer.xml` in $IOT_HOME/analytics/scripts");
|
||||
} else {
|
||||
log.error("Execution plan validation failed: " + validationResponse);
|
||||
}
|
||||
throw new GeoServiceException(
|
||||
"Error occurred while " + action + " geo " + alertType + " alert for " +
|
||||
identifier.getType() + " with id: " + identifier.getId());
|
||||
}
|
||||
return true;
|
||||
} catch (AxisFault axisFault) {
|
||||
throw new GeoServiceException(
|
||||
"Event processor admin service initialization failed while " + action + " geo alert '" +
|
||||
alertType + "' for " + identifier.getType() + " " +
|
||||
"device with id: " + identifier.getId(), axisFault
|
||||
);
|
||||
} catch (IOException e) {
|
||||
throw new GeoServiceException(
|
||||
"Event processor admin service failed while " + action + " geo alert '" +
|
||||
alertType + "' for " + identifier.getType() + " " +
|
||||
"device with id: " + identifier.getId(), e);
|
||||
} catch (JWTClientException e) {
|
||||
throw new GeoServiceException(
|
||||
"JWT token creation failed while " + action + " geo alert '" + alertType + "' for " +
|
||||
identifier.getType() + " device with id:" + identifier.getId(), e);
|
||||
} finally {
|
||||
cleanup(eventprocessorStub);
|
||||
}
|
||||
}
|
||||
|
||||
private String getRegistryPath(String alertType, DeviceIdentifier identifier, String queryName)
|
||||
throws GeoServiceException {
|
||||
String path = "";
|
||||
if (GeoServices.ALERT_TYPE_WITHIN.equals(alertType)) {
|
||||
path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_WITHIN +
|
||||
"/" + identifier.getId() + "/" + queryName;
|
||||
} else if (GeoServices.ALERT_TYPE_EXIT.equals(alertType)) {
|
||||
path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_EXIT +
|
||||
"/" + identifier.getId() + "/" + queryName;
|
||||
} else if (GeoServices.ALERT_TYPE_SPEED.equals(alertType)) {
|
||||
path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_SPEED +
|
||||
"/" + identifier.getId();
|
||||
} else if (GeoServices.ALERT_TYPE_PROXIMITY.equals(alertType)) {
|
||||
path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_PROXIMITY +
|
||||
"/" + identifier.getId() + "/" + queryName;
|
||||
} else if (GeoServices.ALERT_TYPE_STATIONARY.equals(alertType)) {
|
||||
path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_STATIONARY +
|
||||
"/" + identifier.getId() + "/" + queryName;
|
||||
} else if (GeoServices.ALERT_TYPE_TRAFFIC.equals(alertType)) {
|
||||
path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_TRAFFIC +
|
||||
"/" + identifier.getId() + "/" + queryName;
|
||||
} else {
|
||||
throw new GeoServiceException(
|
||||
"Unrecognized execution plan type: " + alertType);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
private String getExecutionPlanName(String alertType, String queryName, String deviceId) {
|
||||
if ("Traffic".equals(alertType)) {
|
||||
return "Geo-ExecutionPlan-Traffic_" + queryName + "_alert";
|
||||
} else {
|
||||
return "Geo-ExecutionPlan-" + alertType + "_" + queryName + "---_" + deviceId + "_alert";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeGeoAlert(String alertType, DeviceIdentifier identifier, String queryName)
|
||||
throws GeoServiceException {
|
||||
removeFromRegistry(alertType, identifier, queryName);
|
||||
String executionPlanName = getExecutionPlanName(alertType, queryName, identifier.getId());
|
||||
EventProcessorAdminServiceStub eventprocessorStub = null;
|
||||
try {
|
||||
eventprocessorStub = getEventProcessorAdminServiceStub();
|
||||
eventprocessorStub.undeployActiveExecutionPlan(executionPlanName);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
throw new GeoServiceException(
|
||||
"Event processor admin service stub invocation failed while removing geo alert '" +
|
||||
alertType +
|
||||
"': " + executionPlanName + " for " +
|
||||
identifier.getType() + " device with id:" + identifier.getId(), e
|
||||
);
|
||||
} catch (JWTClientException e) {
|
||||
throw new GeoServiceException(
|
||||
"JWT token creation failed while removing geo alert '" + alertType + "': " +
|
||||
executionPlanName + " for " +
|
||||
identifier.getType() + " device with id:" + identifier.getId(), e
|
||||
);
|
||||
} finally {
|
||||
cleanup(eventprocessorStub);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeFromRegistry(String alertType, DeviceIdentifier identifier, String queryName)
|
||||
throws GeoServiceException {
|
||||
String path = "unknown";
|
||||
try {
|
||||
path = getRegistryPath(alertType, identifier, queryName);
|
||||
getGovernanceRegistry().delete(path);
|
||||
} catch (RegistryException e) {
|
||||
throw new GeoServiceException(
|
||||
"Error occurred while removing " + alertType + " alert for " + identifier.getType() +
|
||||
" device with id:" + identifier.getId() + " from the path: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
private EventProcessorAdminServiceStub getEventProcessorAdminServiceStub() throws JWTClientException {
|
||||
//send alert to event-processing
|
||||
String eventProcessorAdminServiceWSUrl = Utils.replaceSystemProperty(GeoServices.DAS_URL) +
|
||||
"/services/EventProcessorAdminService";
|
||||
|
||||
//Getting the tenant Domain
|
||||
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
|
||||
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
|
||||
String tenantAdminUser = username + "@" + tenantDomain;
|
||||
|
||||
try {
|
||||
//Create the SSL context with the loaded TrustStore/keystore.
|
||||
SSLContext sslContext = initSSLConnection(tenantAdminUser);
|
||||
JWTClient jwtClient = getJWTClientManagerService().getJWTClient();
|
||||
|
||||
String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64(
|
||||
jwtClient.getJwtToken(tenantAdminUser).getBytes()));
|
||||
|
||||
EventProcessorAdminServiceStub eventprocessorStub = new EventProcessorAdminServiceStub(
|
||||
eventProcessorAdminServiceWSUrl);
|
||||
|
||||
Options eventProcessorOption = eventprocessorStub._getServiceClient().getOptions();
|
||||
if (eventProcessorOption == null) {
|
||||
eventProcessorOption = new Options();
|
||||
}
|
||||
|
||||
List<Header> list = new ArrayList<>();
|
||||
Header httpHeader = new Header();
|
||||
httpHeader.setName(AUTHORIZATION_HEADER);
|
||||
httpHeader.setValue(authValue);
|
||||
list.add(httpHeader);//"https"
|
||||
|
||||
eventProcessorOption.setProperty(HTTPConstants.HTTP_HEADERS, list);
|
||||
eventProcessorOption.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
|
||||
, new Protocol(DEFAULT_HTTP_PROTOCOL
|
||||
, (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
|
||||
, Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
|
||||
eventprocessorStub._getServiceClient().setOptions(eventProcessorOption);
|
||||
|
||||
return eventprocessorStub;
|
||||
} catch (CertificateException | NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException |
|
||||
KeyManagementException | IOException e) {
|
||||
throw new JWTClientException("JWT token creation failed for the Event Processor Stub", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpeedAlerts(DeviceIdentifier identifier) throws GeoServiceException {
|
||||
try {
|
||||
Registry registry = getGovernanceRegistry();
|
||||
Resource resource = registry.get(GeoServices.REGISTRY_PATH_FOR_ALERTS +
|
||||
GeoServices.ALERT_TYPE_SPEED + "/" + identifier.getId());
|
||||
if (resource == null) {
|
||||
return "{'content': false}";
|
||||
}
|
||||
InputStream inputStream = resource.getContentStream();
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(inputStream, writer, "UTF-8");
|
||||
return "{'speedLimit':" + writer.toString() + "}";
|
||||
} catch (RegistryException | IOException e) {
|
||||
return "{'content': false}";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProximityAlerts(DeviceIdentifier identifier) throws GeoServiceException {
|
||||
try {
|
||||
Registry registry = getGovernanceRegistry();
|
||||
Resource resource = registry.get(GeoServices.REGISTRY_PATH_FOR_ALERTS +
|
||||
GeoServices.ALERT_TYPE_PROXIMITY
|
||||
+ "/" + identifier.getId());
|
||||
if (resource != null) {
|
||||
Properties props = resource.getProperties();
|
||||
|
||||
List proxDisObj = (List) props.get(GeoServices.PROXIMITY_DISTANCE);
|
||||
List proxTimeObj = (List) props.get(GeoServices.PROXIMITY_TIME);
|
||||
|
||||
return String.format("{proximityDistance:\"%s\", proximityTime:\"%s\"}",
|
||||
proxDisObj != null ? proxDisObj.get(0).toString() : "",
|
||||
proxTimeObj != null ? proxTimeObj.get(0).toString() : "");
|
||||
} else {
|
||||
return "{'content': false}";
|
||||
}
|
||||
} catch (RegistryException e) {
|
||||
return "{'content': false}";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GeoFence> getStationaryAlerts(DeviceIdentifier identifier) throws GeoServiceException {
|
||||
|
||||
Registry registry = getGovernanceRegistry();
|
||||
String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS +
|
||||
GeoServices.ALERT_TYPE_STATIONARY + "/" + identifier.getId() + "/";
|
||||
Resource resource;
|
||||
try {
|
||||
resource = registry.get(registryPath);
|
||||
} catch (RegistryException e) {
|
||||
log.error("Error while reading the registry path: " + registryPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
List<GeoFence> fences = new ArrayList<>();
|
||||
if (resource != null) {
|
||||
Object contentObj = resource.getContent();
|
||||
|
||||
if (contentObj instanceof String[]) {
|
||||
String[] content = (String[]) contentObj;
|
||||
for (String res : content) {
|
||||
Resource childRes = registry.get(res);
|
||||
Properties props = childRes.getProperties();
|
||||
GeoFence geoFence = new GeoFence();
|
||||
|
||||
InputStream inputStream = childRes.getContentStream();
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(inputStream, writer, "UTF-8");
|
||||
geoFence.setGeoJson(writer.toString());
|
||||
|
||||
List queryNameObj = (List) props.get(GeoServices.QUERY_NAME);
|
||||
geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null);
|
||||
List areaNameObj = (List) props.get(GeoServices.AREA_NAME);
|
||||
geoFence.setAreaName(areaNameObj != null ? areaNameObj.get(0).toString() : null);
|
||||
List sTimeObj = (List) props.get(GeoServices.STATIONARY_TIME);
|
||||
geoFence.setStationaryTime(sTimeObj != null ? sTimeObj.get(0).toString() : null);
|
||||
List fluctRadiusObj = (List) props.get(GeoServices.FLUCTUATION_RADIUS);
|
||||
geoFence.setFluctuationRadius(fluctRadiusObj != null ? fluctRadiusObj.get(0).toString() : null);
|
||||
geoFence.setCreatedTime(childRes.getCreatedTime().getTime());
|
||||
fences.add(geoFence);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fences;
|
||||
} catch (RegistryException | IOException e) {
|
||||
throw new GeoServiceException(
|
||||
"Error occurred while getting the geo alerts for " + identifier.getType() + " with id: " +
|
||||
identifier.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GeoFence> getTrafficAlerts(DeviceIdentifier identifier) throws GeoServiceException {
|
||||
Registry registry = getGovernanceRegistry();
|
||||
String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS +
|
||||
GeoServices.ALERT_TYPE_STATIONARY + "/" + identifier.getId() + "/";
|
||||
Resource resource;
|
||||
try {
|
||||
resource = registry.get(registryPath);
|
||||
} catch (RegistryException e) {
|
||||
log.error("Error while reading the registry path: " + registryPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
List<GeoFence> fences = new ArrayList<>();
|
||||
if (resource != null) {
|
||||
Object contentObj = resource.getContent();
|
||||
if (contentObj instanceof String[]) {
|
||||
String[] content = (String[]) contentObj;
|
||||
for (String res : content) {
|
||||
Resource childRes = registry.get(res);
|
||||
Properties props = childRes.getProperties();
|
||||
|
||||
GeoFence geoFence = new GeoFence();
|
||||
|
||||
InputStream inputStream = childRes.getContentStream();
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(inputStream, writer, "UTF-8");
|
||||
geoFence.setGeoJson(writer.toString());
|
||||
|
||||
List queryNameObj = (List) props.get(GeoServices.QUERY_NAME);
|
||||
geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null);
|
||||
List sNameObj = (List) props.get(GeoServices.STATIONARY_NAME);
|
||||
geoFence.setAreaName(sNameObj != null ? sNameObj.get(0).toString() : null);
|
||||
geoFence.setCreatedTime(childRes.getCreatedTime().getTime());
|
||||
fences.add(geoFence);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fences;
|
||||
} catch (RegistryException | IOException e) {
|
||||
throw new GeoServiceException(
|
||||
"Error occurred while getting the geo alerts for " + identifier.getType() + " with id: " +
|
||||
identifier.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private Registry getGovernanceRegistry() throws GeoServiceException {
|
||||
try {
|
||||
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
|
||||
return DeviceManagementDataHolder.getInstance().getRegistryService()
|
||||
.getGovernanceSystemRegistry(
|
||||
tenantId);
|
||||
} catch (RegistryException e) {
|
||||
throw new GeoServiceException(
|
||||
"Error in retrieving governance registry instance: " +
|
||||
e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String parseTemplate(String alertType, Map<String, String> parseMap) throws GeoServiceException {
|
||||
String templatePath = "alerts/Geo-ExecutionPlan-" + alertType + "_alert.siddhiql";
|
||||
InputStream resource = getClass().getClassLoader().getResourceAsStream(templatePath);
|
||||
if (resource == null) {
|
||||
throw new GeoServiceException("Could not find template in path : " + templatePath);
|
||||
}
|
||||
try {
|
||||
//Read template
|
||||
String template = IOUtils.toString(resource, StandardCharsets.UTF_8.toString());
|
||||
//Replace variables
|
||||
for (Map.Entry<String, String> parseEntry : parseMap.entrySet()) {
|
||||
String find = "\\$" + parseEntry.getKey();
|
||||
template = template.replaceAll(find, parseEntry.getValue());
|
||||
}
|
||||
return template;
|
||||
} catch (IOException e) {
|
||||
throw new GeoServiceException(
|
||||
"Error occurred while populating the template for the Within Alert", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRegistry(String path, DeviceIdentifier identifier, Object content, Map<String, String> options)
|
||||
throws GeoServiceException {
|
||||
try {
|
||||
|
||||
Registry registry = getGovernanceRegistry();
|
||||
Resource newResource = registry.newResource();
|
||||
newResource.setContent(content);
|
||||
newResource.setMediaType("application/json");
|
||||
for (Map.Entry<String, String> option : options.entrySet()) {
|
||||
newResource.addProperty(option.getKey(), option.getValue());
|
||||
}
|
||||
registry.put(path, newResource);
|
||||
} catch (RegistryException e) {
|
||||
throw new GeoServiceException(
|
||||
"Error occurred while setting the Within Alert for " + identifier.getType() + " with id: " +
|
||||
identifier.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the keystore.
|
||||
*
|
||||
* @param keyStorePath - the path of the keystore
|
||||
* @param keyStorePassword - the keystore password
|
||||
*/
|
||||
private KeyStore loadKeyStore(String keyStorePath, char[] keyStorePassword)
|
||||
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
|
||||
InputStream fis = null;
|
||||
try {
|
||||
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
|
||||
fis = new FileInputStream(keyStorePath);
|
||||
keyStore.load(fis, keyStorePassword);
|
||||
return keyStore;
|
||||
} finally {
|
||||
if (fis != null) {
|
||||
fis.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the trustore
|
||||
*
|
||||
* @param trustStorePath - the trustore path in the filesystem.
|
||||
* @param tsPassword - the truststore password
|
||||
*/
|
||||
private KeyStore loadTrustStore(String trustStorePath, char[] tsPassword)
|
||||
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
|
||||
|
||||
InputStream fis = null;
|
||||
try {
|
||||
KeyStore trustStore = KeyStore.getInstance(TRUST_STORE_TYPE);
|
||||
fis = new FileInputStream(trustStorePath);
|
||||
trustStore.load(fis, tsPassword);
|
||||
return trustStore;
|
||||
} finally {
|
||||
if (fis != null) {
|
||||
fis.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the SSL Context
|
||||
*/
|
||||
private SSLContext initSSLConnection(String tenantAdminUser)
|
||||
throws NoSuchAlgorithmException, UnrecoverableKeyException,
|
||||
KeyStoreException, KeyManagementException, IOException, CertificateException {
|
||||
String keyStorePassword = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Password");
|
||||
String trustStorePassword = ServerConfiguration.getInstance().getFirstProperty(
|
||||
"Security.TrustStore.Password");
|
||||
String keyStoreLocation = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Location");
|
||||
String trustStoreLocation = ServerConfiguration.getInstance().getFirstProperty(
|
||||
"Security.TrustStore.Location");
|
||||
|
||||
//Call to load the keystore.
|
||||
KeyStore keyStore = loadKeyStore(keyStoreLocation, keyStorePassword.toCharArray());
|
||||
//Call to load the TrustStore.
|
||||
KeyStore trustStore = loadTrustStore(trustStoreLocation, trustStorePassword.toCharArray());
|
||||
|
||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_TYPE);
|
||||
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TRUST_MANAGER_TYPE);
|
||||
trustManagerFactory.init(trustStore);
|
||||
|
||||
// Create and initialize SSLContext for HTTPS communication
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance(SSLV3);
|
||||
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
|
||||
SSLContext.setDefault(sslContext);
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
private void cleanup(Stub stub) {
|
||||
if (stub != null) {
|
||||
try {
|
||||
stub.cleanup();
|
||||
} catch (AxisFault axisFault) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static JWTClientManagerService getJWTClientManagerService() {
|
||||
JWTClientManagerService jwtClientManagerService;
|
||||
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||
jwtClientManagerService = (JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
|
||||
if (jwtClientManagerService == null) {
|
||||
String msg = "jwtClientManagerServicehas not initialized.";
|
||||
log.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
return jwtClientManagerService;
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('$executionPlanName')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string);
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string);
|
||||
|
||||
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==false and id == "$deviceId"]#geodashboard:subscribe()
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is outside $areaName area!!!" as information
|
||||
insert into dataOut;
|
||||
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=false and id == "$deviceId"]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,140 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('Geo-ExecutionPlan-Proximity_alert')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string );
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut ( id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string );
|
||||
|
||||
@IndexBy('id')
|
||||
define table ProximityTable(id string, timeStamp long);
|
||||
|
||||
@IndexBy('id')
|
||||
define table AlertsTable(id string , proximityWith string, eventId string);
|
||||
|
||||
from dataIn#geodashboard:subscribe()
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId
|
||||
insert into initialStream;
|
||||
|
||||
from initialStream[type == 'STOP']
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from initialStream[type != 'STOP']
|
||||
select *
|
||||
insert into objectInitialStream;
|
||||
|
||||
from objectInitialStream#geo:proximity(id,longitude,latitude, $proximityDistance)
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith
|
||||
insert into proxymityStream;
|
||||
|
||||
from proxymityStream[AlertsTable.id == proxymityStream.id in AlertsTable]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable
|
||||
insert into innerStreamOne;
|
||||
|
||||
from proxymityStream[not(AlertsTable.id == proxymityStream.id in AlertsTable)]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable
|
||||
insert into innerStreamOne;
|
||||
|
||||
from proxymityStream[AlertsTable.id == proxymityStream.proximityWith in AlertsTable]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable
|
||||
insert into innerStreamSeven;
|
||||
|
||||
from proxymityStream[not(AlertsTable.id == proxymityStream.proximityWith in AlertsTable)]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable
|
||||
insert into innerStreamSeven;
|
||||
|
||||
from innerStreamOne[inCloseProximity == true AND not(inAlertTable)]
|
||||
select id,str:concat(",",proximityWith) as proximityWith , eventId
|
||||
insert into AlertsTable;
|
||||
|
||||
from innerStreamSeven[inCloseProximity == true AND not(inAlertTable)]
|
||||
select proximityWith as id,str:concat(",",id) as proximityWith , eventId
|
||||
insert into AlertsTable;
|
||||
|
||||
from innerStreamOne[innerStreamOne.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable
|
||||
on innerStreamOne.id == AlertsTable.id
|
||||
select innerStreamOne.id as id, str:concat(",", innerStreamOne.proximityWith, AlertsTable.proximityWith) as proximityWith, innerStreamOne.eventId as eventId
|
||||
insert into updateStream;
|
||||
|
||||
from innerStreamSeven[innerStreamSeven.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable
|
||||
on innerStreamSeven.proximityWith == AlertsTable.id
|
||||
select innerStreamSeven.proximityWith as id, str:concat(",", innerStreamSeven.id, AlertsTable.proximityWith) as proximityWith, innerStreamSeven.eventId as eventId
|
||||
insert into updateStream;
|
||||
|
||||
from innerStreamOne[innerStreamOne.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable
|
||||
on innerStreamOne.id == AlertsTable.id
|
||||
select innerStreamOne.id as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamOne.proximityWith), "") as proximityWith, innerStreamOne.eventId as eventId
|
||||
insert into updateStream;
|
||||
|
||||
from innerStreamSeven[innerStreamSeven.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable
|
||||
on innerStreamSeven.proximityWith == AlertsTable.id
|
||||
select innerStreamSeven.proximityWith as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamSeven.id), "") as proximityWith, innerStreamSeven.eventId as eventId
|
||||
insert into updateStream;
|
||||
|
||||
from updateStream
|
||||
select *
|
||||
update AlertsTable
|
||||
on id== AlertsTable.id;
|
||||
|
||||
from updateStream[proximityWith == ""]
|
||||
delete AlertsTable
|
||||
on id== AlertsTable.id;
|
||||
|
||||
from objectInitialStream[AlertsTable.id == objectInitialStream.id in AlertsTable]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId, true as inAlertTable
|
||||
insert into publishStream;
|
||||
|
||||
from objectInitialStream[not(AlertsTable.id == objectInitialStream.id in AlertsTable)]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId, false as inAlertTable
|
||||
insert into publishStream;
|
||||
|
||||
from publishStream[inAlertTable == true]#window.length(0) join AlertsTable
|
||||
on publishStream.id== AlertsTable.id
|
||||
select publishStream.id as id, publishStream.latitude as latitude, publishStream.longitude as longitude, publishStream.timeStamp as timeStamp, publishStream.type as type, publishStream.speed as speed, publishStream.heading as heading, publishStream.eventId as eventId, AlertsTable.proximityWith as proximityInfo
|
||||
insert into innerStreamTwo;
|
||||
|
||||
from publishStream[inAlertTable == false]
|
||||
delete ProximityTable on ProximityTable.id==id;
|
||||
|
||||
from publishStream[inAlertTable == false]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamTwo[ProximityTable.id == innerStreamTwo.id in ProximityTable]
|
||||
insert into innerStreamThree;
|
||||
|
||||
from innerStreamThree#window.length(0) join ProximityTable
|
||||
on innerStreamThree.id == ProximityTable.id
|
||||
select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId, ProximityTable.timeStamp as storedTime, innerStreamThree.proximityInfo as proximityInfo
|
||||
insert into innerStreamFour;
|
||||
|
||||
from innerStreamFour[(timeStamp - storedTime) >= $proximityTime]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,proximityInfo,"true" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamFour[(timeStamp - storedTime) < $proximityTime]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , proximityInfo ,"false" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)]
|
||||
select innerStreamTwo.id, innerStreamTwo.timeStamp
|
||||
insert into ProximityTable;
|
||||
|
||||
from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from dataOutStream[isProximity == 'true']
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,"WARNING" as state,str:concat("Proximity with "," ",proximityInfo) as information
|
||||
insert into dataOut;
|
||||
|
||||
from dataOutStream[isProximity == 'false']
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,20 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('Geo-ExecutionPlan-Speed---$deviceId_alert')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string);
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string);
|
||||
|
||||
from dataIn[speed >= $speedAlertValue and id == "$deviceId"]#geodashboard:subscribe()
|
||||
select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, "This device movement is not normal!!" as information
|
||||
insert into dataOut;
|
||||
from dataIn[speed < $speedAlertValue and id == "$deviceId"]
|
||||
select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, "This device movement is normal" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,89 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('$executionPlanName')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string);
|
||||
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string);
|
||||
|
||||
@IndexBy('id')
|
||||
define table StationeryTable(id string, timeStamp long);
|
||||
|
||||
@IndexBy('id')
|
||||
define table AlertsTable(id string, stationary bool);
|
||||
|
||||
from dataIn#geodashboard:subscribe()
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,geo:within(longitude,latitude,"$geoFenceGeoJSON") as isWithin
|
||||
insert into innerStreamOne;
|
||||
|
||||
from innerStreamOne[isWithin == false]
|
||||
delete StationeryTable on StationeryTable.id==id;
|
||||
|
||||
from innerStreamOne[isWithin == false]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamOne[isWithin == true]#geo:stationary(id,longitude,latitude, $fluctuationRadius)
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,stationary
|
||||
insert into innerStreamTwo;
|
||||
|
||||
from innerStreamTwo[innerStreamTwo.stationary == true]
|
||||
select innerStreamTwo.id, innerStreamTwo.stationary
|
||||
insert into AlertsTable;
|
||||
|
||||
from innerStreamTwo[innerStreamTwo.stationary == false]
|
||||
delete AlertsTable on AlertsTable.id==id;
|
||||
|
||||
from innerStreamTwo[innerStreamTwo.stationary == false]
|
||||
delete StationeryTable on StationeryTable.id==id;
|
||||
|
||||
from innerStreamOne[isWithin == true AND not(AlertsTable.id == innerStreamOne.id in AlertsTable)]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamOne[isWithin == true AND AlertsTable.id == innerStreamOne.id in AlertsTable]
|
||||
insert into innerStreamThree;
|
||||
|
||||
from innerStreamThree#window.length(0) join AlertsTable
|
||||
on innerStreamThree.id == AlertsTable.id
|
||||
select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId
|
||||
insert into innerStreamFour;
|
||||
|
||||
from innerStreamFour[not(StationeryTable.id == innerStreamFour.id in StationeryTable)]
|
||||
select innerStreamFour.id, innerStreamFour.timeStamp
|
||||
insert into StationeryTable;
|
||||
|
||||
from innerStreamOne[isWithin == true AND not(StationeryTable.id == innerStreamOne.id in StationeryTable)]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamOne[isWithin == true AND StationeryTable.id == innerStreamOne.id in StationeryTable]
|
||||
insert into innerStreamFive;
|
||||
|
||||
from innerStreamFive#window.length(0) join StationeryTable
|
||||
on innerStreamFive.id == StationeryTable.id
|
||||
select innerStreamFive.id , innerStreamFive.latitude, innerStreamFive.longitude,innerStreamFive.timeStamp, innerStreamFive.type, innerStreamFive.speed, innerStreamFive.heading ,innerStreamFive.eventId, StationeryTable.timeStamp as storedTime
|
||||
insert into innerStreamSix;
|
||||
|
||||
from innerStreamSix[(timeStamp - storedTime) >= $stationeryTime]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"true" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamSix[(timeStamp - storedTime) < $stationeryTime]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"false" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from dataOutStream[isStationary == 'true']
|
||||
select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, "This device is in $stationeryName area!!!" as information
|
||||
insert into dataOut;
|
||||
|
||||
from dataOutStream[isStationary == 'false']
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,17 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('$executionPlanName')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('rawGeoStream:1.0.0')
|
||||
define stream dataIn (id string, timeStamp long, geometry string, state string, information string);
|
||||
|
||||
@Export('AlertsNotifications:1.0.0')
|
||||
define stream dataOut (id string, state string, information string, timeStamp long, latitude double, longitude double);
|
||||
|
||||
from dataIn[geo:intersects(geometry, "$geoFenceGeoJSON")==true and geodashboard:needToNotify(id, str:concat(information, state), "sendFirst") == true and id == $deviceId]
|
||||
select id, state, str:concat("Traffic alert in $areaName. State: ", state, " ", information) as information, timeStamp, 0.0 as latitude, 0.0 as longitude
|
||||
insert into dataOut
|
@ -0,0 +1,20 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('$executionPlanName')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string);
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string);
|
||||
|
||||
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==true and id == "$deviceId"]#geodashboard:subscribe()
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information
|
||||
insert into dataOut;
|
||||
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=true and id == "$deviceId"]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,715 @@
|
||||
{{!
|
||||
Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
|
||||
WSO2 Inc. licenses this file to you under the Apache License,
|
||||
Version 2.0 (the "License"); you may not use this file except
|
||||
in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
}}
|
||||
|
||||
{{#zone "topCss"}}
|
||||
{{css "css/app.css" combine=false}}
|
||||
{{css "css/map.css" combine=false}}
|
||||
{{css "css/leaflet.css" combine=false}}
|
||||
{{css "css/L.Control.Locate.css" combine=false}}
|
||||
{{css "css/MarkerCluster.Default.css" combine=false}}
|
||||
{{css "css/leaflet_fullscreen/leaflet.fullscreen.css" combine=false}}
|
||||
{{css "css/leaflet/leaflet.draw.css" combine=false}}
|
||||
|
||||
{{css "css/d3/c3.css" combine=false}}
|
||||
{{css "css/bootstrap-datepicker.min.css" combine=false}}
|
||||
|
||||
<style>
|
||||
.datepicker-inline {
|
||||
margin:0 auto;
|
||||
}
|
||||
</style>
|
||||
{{/zone}}
|
||||
|
||||
{{#zone "content"}}
|
||||
<div id="alerts-common"></div>
|
||||
{{/zone}}
|
||||
|
||||
<span id="geo-charts" data-ws-endpoint="{{wsEndpoint}}" data-ws-token="{{wsToken}}" data-geo-public-uri="{{@unit.publicUri}}"
|
||||
data-device-location="{{lastLocation}}"></span>
|
||||
|
||||
<div class="map-wrapper">
|
||||
{{#unless @unit.params.hideSearch}}
|
||||
<div class="navbar-collapse collapse" style="display:inline-block;">
|
||||
<ul class="nav navbar-nav-right">
|
||||
<li>
|
||||
<form id="mapSearch" class="navbar-form" role="search"
|
||||
onsubmit="focusOnSpatialObject($(this).find('#searchbox').val());return false;">
|
||||
<div class="form-group has-feedback">
|
||||
<input autofocus="true" id="searchbox" type="text" placeholder="Search"
|
||||
class="form-control typeahead">
|
||||
<span id="searchicon" class="fa fa-search form-control-feedback"></span>
|
||||
</div>
|
||||
<input style="visibility: hidden; position: fixed;" type="submit"/>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
<div id="" style="height: 93vh;">
|
||||
<!-- Sidebar -->
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
|
||||
<div id="predictionResults" style="background: darkgray;display: none;border-radius: 13px;height: 94%;padding: 0"
|
||||
class="col-md-2 pull-right">
|
||||
<div class="panel-heading text-center">
|
||||
<h4> Prediction Results For: <span id="predictionResultsID" class="text-info"></span>
|
||||
<i id="objectInfoCloseButton" class="fa fa-times pull-right"
|
||||
onclick="$('#predictionResults').animate({width: ['toggle','swing']},200);toggeled = false;spatialObject = currentSpatialObjects[selectedSpatialObject];spatialObject.removePath();spatialObject.marker.closePopup();selectedSpatialObject = null;">
|
||||
</i>
|
||||
</h4>
|
||||
</div>
|
||||
<br>
|
||||
<div class="panel panel-default" style="overflow: auto;box-shadow: 0 0 8px 0 #635749">
|
||||
<div class="panel-heading text-center"><h4>Prediction</h4>
|
||||
</div>
|
||||
<br>
|
||||
<div class="panel-body">
|
||||
<div style="max-height: 100%;margin: 0;border: none;margin-left: -25px" id="prediction_chart_div"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="loading">
|
||||
<div class="loading-indicator">
|
||||
<div class="progress progress-striped active">
|
||||
<div class="progress-bar progress-bar-info" style="width: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="aboutModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Welcome to the BootLeaf template!</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs" id="aboutTabs">
|
||||
<li class="active"><a href="#about" data-toggle="tab"><i class="fa fa-question-circle"></i> About
|
||||
the project</a></li>
|
||||
<li><a href="#contact" data-toggle="tab"><i class="fa fa-envelope"></i> Contact us</a></li>
|
||||
<li><a href="#disclaimer" data-toggle="tab"><i class="fa fa-exclamation-circle"></i> Disclaimer</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-globe"></i> Metadata
|
||||
<b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#boroughs-tab" data-toggle="tab">Boroughs</a></li>
|
||||
<li><a href="#subway-lines-tab" data-toggle="tab">Subway Lines</a></li>
|
||||
<li><a href="#theaters-tab" data-toggle="tab">Theaters</a></li>
|
||||
<li><a href="#museums-tab" data-toggle="tab">Museums</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="aboutTabsContent" style="padding-top: 10px;">
|
||||
<div class="tab-pane fade active in" id="about">
|
||||
<p>A simple, responsive template for building web mapping applications with <a
|
||||
href="http://getbootstrap.com/">Bootstrap 3</a>, <a href="http://leafletjs.com/"
|
||||
target="_blank">Leaflet</a>, and <a
|
||||
href="http://twitter.github.io/typeahead.js/" target="_blank">typeahead.js</a>. Open
|
||||
source, MIT licensed, and available on <a href="https://github.com/bmcbride/bootleaf"
|
||||
target="_blank">GitHub</a>.</p>
|
||||
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">Features</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">Fullscreen mobile-friendly map template with responsive
|
||||
navbar and modal placeholders
|
||||
</li>
|
||||
<li class="list-group-item">jQuery loading of external GeoJSON files</li>
|
||||
<li class="list-group-item">Logical multiple layer marker clustering via the <a
|
||||
href="https://github.com/Leaflet/Leaflet.markercluster" target="_blank">leaflet
|
||||
marker cluster plugin</a></li>
|
||||
<li class="list-group-item">Elegant client-side multi-layer feature search with
|
||||
autocomplete using <a href="http://twitter.github.io/typeahead.js/" target="_blank">typeahead.js</a>
|
||||
</li>
|
||||
<li class="list-group-item">Responsive sidebar feature list with sorting and filtering
|
||||
via <a href="http://listjs.com/" target="_blank">list.js</a></li>
|
||||
<li class="list-group-item">Marker icons included in grouped layer control via the <a
|
||||
href="https://github.com/ismyrnow/Leaflet.groupedlayercontrol" target="_blank">grouped
|
||||
layer control plugin</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="disclaimer" class="tab-pane fade text-danger">
|
||||
<p>The data provided on this site is for informational and planning purposes only.</p>
|
||||
|
||||
<p>Absolutely no accuracy or completeness guarantee is implied or intended. All information on
|
||||
this map is subject to such variations and corrections as might result from a complete title
|
||||
search and/or accurate field survey.</p>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="contact">
|
||||
<form id="contact-form">
|
||||
<div class="well well-sm">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label for="first-name">First Name:</label>
|
||||
<input type="text" class="form-control" id="first-name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="last-email">Last Name:</label>
|
||||
<input type="text" class="form-control" id="last-email">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email:</label>
|
||||
<input type="text" class="form-control" id="email">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label for="message">Message:</label>
|
||||
<textarea class="form-control" rows="8" id="message"></textarea>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<p>
|
||||
<button type="submit" class="btn btn-primary pull-right"
|
||||
data-dismiss="modal">Submit
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="boroughs-tab">
|
||||
<p>Borough data courtesy of <a
|
||||
href="http://www.nyc.gov/html/dcp/html/bytes/meta_dis_nyboroughwi.shtml"
|
||||
target="_blank">New York City Department of City Planning</a></p>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="subway-lines-tab">
|
||||
<p><a href="http://spatialityblog.com/2010/07/08/mta-gis-data-update/#datalinks"
|
||||
target="_blank">MTA Subway data</a> courtesy of the <a
|
||||
href="http://www.urbanresearch.org/about/cur-components/cuny-mapping-service"
|
||||
target="_blank">CUNY Mapping Service at the Center for Urban Research</a></p>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="theaters-tab">
|
||||
<p>Theater data courtesy of <a
|
||||
href="https://data.cityofnewyork.us/Recreation/Theaters/kdu2-865w" target="_blank">NYC
|
||||
Department of Information & Telecommunications (DoITT)</a></p>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="museums-tab">
|
||||
<p>Museum data courtesy of <a
|
||||
href="https://data.cityofnewyork.us/Recreation/Museums-and-Galleries/sat5-adpb"
|
||||
target="_blank">NYC Department of Information & Telecommunications (DoITT)</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="attributionModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 id = "title" class="modal-title">
|
||||
WSO2 Geo Dashboard
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="attribution"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal" id="addTileServer" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content" style="width:50%; margin:0 auto;">
|
||||
<div class="modal-header"
|
||||
style="cursor: move;background: #f9f9f9;-webkit-box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);-moz-box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">
|
||||
<!– TODO: Trigger bootstrap tooltip $('#aboutTileUrl').tooltip(); to enable tooltip –>
|
||||
Add tiler server URL <sup id="aboutTileUrl" style="cursor: pointer;" data-toggle="tooltip"
|
||||
title="What is a tile URL?"><i class="fa fa-question" style="color: #39F;"
|
||||
data-toggle="collapse"
|
||||
data-target="#collapseOne"></i></sup>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="urlInput">
|
||||
<div style="height: 0px;" id="collapseOne" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<p>A string of the following form:</p>
|
||||
<pre><code class="javascript"><span class="string">'http://{s}.somedomain.com/blabla/{z}/{x}/{y}.png'</span></code></pre>
|
||||
<p><code class="javascript">{s}</code> means one of the available subdomains (used
|
||||
sequentially to help with browser parallel requests per domain limitation; subdomain
|
||||
values are specified in options; <code class="javascript">a</code>, <code
|
||||
class="javascript">b</code> or <code class="javascript">c</code> by default, can
|
||||
be omitted), <code class="javascript">{z}</code> — zoom level, <code class="javascript">{x}</code>
|
||||
and <code class="javascript">{y}</code> — tile coordinates.</p>
|
||||
|
||||
<p>You can use custom keys in the template, which will be <a
|
||||
href="#util-template">evaluated</a> from TileLayer options, like this:</p>
|
||||
<pre><code class="javascript">L.tileLayer(<span class="string">'http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png'</span>,
|
||||
{foo: <span class="string">'bar'</span>});</code></pre>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon"><i class="fa fa-italic"></i></span>
|
||||
<input autofocus="enable" id="tileName" type="text" class="form-control"
|
||||
placeholder="Tile URL name">
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon"><i class="fa fa-globe"></i></span>
|
||||
<input id="tileUrl" class="form-control" type="text"
|
||||
placeholder="http://{s}.somedomain.com/blabla/{z}/{x}/{y}.png">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-info" type="button" onclick="addTileUrl()"><i class="fa fa-plus"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<div class="panel panel-default" style="width: 80%;">
|
||||
<div>
|
||||
<h4 class="panel-title" style="font-size: 12px;line-height: 1.5;">
|
||||
<button style="text-align: left;" class="btn btn-default btn-xs btn-block collapsed"
|
||||
onclick="$('.fa-chevron-right').toggleClass('fa-rotate-90')"
|
||||
data-toggle="collapse" data-parent="#accordion" href="#tileUrlOptions">
|
||||
<i class="fa fa-chevron-right"></i> Options
|
||||
</button>
|
||||
</h4>
|
||||
</div>
|
||||
<div style="height: 0px;" id="tileUrlOptions" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="input-group input-group-sm col-sm-9">
|
||||
<small class="text-primary">
|
||||
<label class="col-sm-2 control-label" for="sub_domains">Sub-domains</label>
|
||||
</small>
|
||||
<input id="sub_domains" type="text" class="form-control"
|
||||
placeholder="Enter sub-domains in CSV format">
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="input-group input-group-sm col-sm-9">
|
||||
<small class="text-primary">
|
||||
<label class="col-sm-9 control-label" for="maxzoom">Max zoom level</label>
|
||||
</small>
|
||||
<input id="maxzoom" type="text" class="form-control"
|
||||
placeholder="Number between(around) 1~19">
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<div class="input-group input-group-sm col-sm-9">
|
||||
<small class="text-primary">
|
||||
<label class="col-sm-2 control-label" for="data_attribution">Attribution</label>
|
||||
</small>
|
||||
<input id="data_attribution" type="text" class="form-control"
|
||||
placeholder="Enter attribution">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal" id="addWmsUrl" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content" style="width:50%; margin:0 auto;">
|
||||
<div class="modal-header"
|
||||
style="cursor: move;background: #f9f9f9;-webkit-box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);-moz-box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">
|
||||
<sup id="aboutWms" style="cursor: pointer;" data-toggle="tooltip"
|
||||
title="What WMS end-point"><i class="fa fa-question"
|
||||
style="color: #39F;"
|
||||
data-toggle="collapse"
|
||||
data-target="#wmsOverview"></i></sup>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
<div style="height: 0px;" id="wmsOverview" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
The OpenGIS® Web Map Service Interface Standard (WMS) provides a simple HTTP interface for
|
||||
requesting geo-registered map images from one or more distributed geospatial databases.
|
||||
A WMS request defines the geographic layer(s) and area of interest to be processed.
|
||||
The response to the request is one or more geo-registered map images (returned as JPEG, PNG,
|
||||
etc) that can be displayed in a browser application.
|
||||
The interface also supports the ability to specify whether the returned images should be
|
||||
transparent so that layers from multiple servers can be combined or not.
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon"><i class="fa fa-italic"></i></span>
|
||||
<input autofocus="enable" id="serviceName" type="text" class="form-control"
|
||||
placeholder="Service provider name">
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon"><i class="fa fa-align-justify"></i></span>
|
||||
<input autofocus="enable" id="layers" type="text" class="form-control"
|
||||
placeholder="Service layers as comma seperated values">
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon">V.</span>
|
||||
<input autofocus="enable" id="wmsVersion" type="text" class="form-control"
|
||||
placeholder="WMS version (i.e: 1.1.1 or 1.3.0)">
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon"><i class="fa fa-globe"></i></span>
|
||||
<input id="serviceEndPoint" class="form-control" type="text"
|
||||
placeholder="http(s)://sedac.ciesin.columbia.edu/geoserver/wms">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-info" type="button" onclick="addWmsEndPoint()"><i
|
||||
class="fa fa-plus"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="panel panel-default" style="width: 80%;">
|
||||
<div>
|
||||
<h4 class="panel-title" style="font-size: 12px;line-height: 1.5;">
|
||||
<button style="text-align: left;" class="btn btn-default btn-xs btn-block collapsed"
|
||||
onclick="$('.fa-chevron-right').toggleClass('fa-rotate-90')"
|
||||
data-toggle="collapse" data-parent="#accordion" href="#wmsOptions">
|
||||
<i class="fa fa-chevron-right"></i> Options
|
||||
</button>
|
||||
</h4>
|
||||
</div>
|
||||
<div style="height: 0px;" id="wmsOptions" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="input-group input-group-sm col-sm-11">
|
||||
<small class="text-primary">
|
||||
<label class="col-sm-6 control-label" for="outputFormat">Output format</label>
|
||||
</small>
|
||||
<input id="outputFormat" type="text" class="form-control"
|
||||
placeholder="Output format (i.e: image/png, image/jpeg, image/svg)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="commonModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="editWithinGeoJSON" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">
|
||||
</h4>
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h4>
|
||||
Adding GeoJson
|
||||
<br>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="col-lg-8 col-md-8 col-centered">
|
||||
<div>
|
||||
<label for="importGeoJsonFile">Import GeoJson</label>
|
||||
<input id="importGeoJsonFile" type="file">
|
||||
<hr />
|
||||
<label for="enterGeoJson">Enter GeoJson</label>
|
||||
<textarea id="enterGeoJson" class="form-control" rows="10"></textarea>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<button id="updateGeoJson" class="btn btn-primary" onclick="importGeoJson()">Import</button>
|
||||
<button type="button" class="btn btn-default" onclick="closeAll()">Cancel</button>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: none">
|
||||
<div id="markerPopup" class="popover top">
|
||||
<div class="arrow"></div>
|
||||
<h3 class="popover-title">ID <span id="objectId"></span></h3>
|
||||
<div class="popover-content">
|
||||
<h6>Information</h6>
|
||||
<p id="information" class="bg-primary" style="margin: 0px;padding: 0px;"></p>
|
||||
<h6>Speed<span class="label label-primary pull-right"><span id="speed"></span> km/h</span></h6>
|
||||
<h6>Heading<span id="heading" class="label label-primary pull-right"></span></h6>
|
||||
<button type="button" class="btn btn-info btn-xs" onClick="toggleSpeedGraph();return false;">Speed Graph</button>
|
||||
<button type="button" class="btn btn-info btn-xs" onClick="focusOnRecentHistorySpatialObject();return false;">Recent History</button>
|
||||
<button type="button" class="btn btn-info btn-xs" onClick="popupDateRange();">Full History</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="dateRangePopup">
|
||||
<div>
|
||||
<label> From: <input id="timeFrom" type="text"> </label>
|
||||
<label> To: <input id="timeTo" type="text"> </label>
|
||||
<button type="button" class="btn btn-info btn-xs" onClick="focusOnHistorySpatialObject(document.getElementById('objectId').innerHTML, document.getElementById('timeFrom').value, document.getElementById('timeTo').value);return false;">Full History</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="markerPopupStop" class="popover top">
|
||||
<div class="arrow"></div>
|
||||
<h3 class="popover-title">ID <span id="objectId"></span></h3>
|
||||
|
||||
<div class="popover-content">
|
||||
<h6>Information</h6>
|
||||
|
||||
<p id="information" class="bg-primary" style="margin: 0px;padding: 0px;"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="areaPopup" class="popover top">
|
||||
<div class="arrow"></div>
|
||||
<h3 class="popover-title">ID <span id="objectId"></span></h3>
|
||||
<div class="popover-content">
|
||||
<h6>Severity</h6>
|
||||
|
||||
<p id="severity" class="bg-primary" style="margin: 0px;padding: 0px;"></p>
|
||||
</div>
|
||||
<div class="popover-content">
|
||||
<h6>Information</h6>
|
||||
|
||||
<p id="information" class="bg-primary" style="margin: 0px;padding: 0px;"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="setWithinAlert">
|
||||
<form role="form" style="width: auto;">
|
||||
<div class="form-group">
|
||||
<label class="text-primary" for="areaName">Fence name</label>
|
||||
<input class="form-control" id="areaName" placeholder="Fence name" type="text">
|
||||
<span class="help-block">Name of the selected area(i.e colombo)</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="btn-group btn-group-sm btn-group-justified">
|
||||
<div class="btn-group">
|
||||
<button id="addWithinAlert" onclick="setWithinAlert($(this).attr('leaflet_id'))" type="button"
|
||||
class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left"
|
||||
title="Save selected area for alerts">Save
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="editGeoJson"
|
||||
onclick="$('#editWithinGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editWithinGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editWithinGeoJSON').modal('toggle')"
|
||||
type="button" class="btn btn-default btn-xs">Edit
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a id="exportGeoJson" download="geoJson.json" href="#"
|
||||
onclick="exportToGeoJSON(this, JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'))"
|
||||
class="btn btn-default btn-xs" data-toggle="tooltip" data-placement="left"
|
||||
title="Export selected area as a geoJson file">Export</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="setExitAlert">
|
||||
<form role="form" style="width: auto;">
|
||||
<div class="form-group">
|
||||
<label class="text-primary" for="areaName">Fence name</label>
|
||||
<input class="form-control" id="areaName" placeholder="Fence name" type="text">
|
||||
<span class="help-block">Name of the selected area(i.e colombo)</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="btn-group btn-group-sm btn-group-justified">
|
||||
<div class="btn-group">
|
||||
<button id="addExitAlert" onclick="setExitAlert($(this).attr('leaflet_id'))" type="button"
|
||||
class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left"
|
||||
title="Save selected area for alerts">Save
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="editGeoJson"
|
||||
onclick="$('#editExitGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editExitGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editExitGeoJSON').modal('toggle')"
|
||||
type="button" class="btn btn-default btn-xs">Edit
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a id="exportGeoJson" download="geoJson.json" href="#"
|
||||
onclick="exportToGeoJSON(this, JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'))"
|
||||
class="btn btn-default btn-xs" data-toggle="tooltip" data-placement="left"
|
||||
title="Export selected area as a geoJson file">Export</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="templateLoader"></div>
|
||||
<div id="setStationeryAlert">
|
||||
<form role="form" style="width: auto;">
|
||||
<div class="form-group">
|
||||
<label class="text-primary" for="areaName">Fence name</label>
|
||||
<input class="form-control" id="areaName" placeholder="Stationery name" type="text">
|
||||
<span class="help-block">Name of the selected area(i.e colombo)</span>
|
||||
|
||||
<label class="text-primary" for="fRadius">Fluctuation radius</label>
|
||||
<input class="form-control" id="fRadius" onblur="reformatRadius(this.form.fRadius.value);" placeholder="m" type="text">
|
||||
|
||||
<label class="text-primary" for="time">Time</label>
|
||||
<input class="form-control" id="time" placeholder="Seconds" type="text">
|
||||
</div>
|
||||
<div>
|
||||
<div class="btn-group btn-group-sm btn-group-justified">
|
||||
<div class="btn-group">
|
||||
<button id="addStationeryAlert" onclick="setStationeryAlert($(this).attr('leaflet_id'))" type="button"
|
||||
class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left"
|
||||
title="Save selected area for alerts">Save
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="editGeoJson"
|
||||
onclick="$('#editWithinGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editWithinGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editWithinGeoJSON').modal('toggle')"
|
||||
type="button" class="btn btn-default btn-xs">Edit
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a id="exportGeoJson" download="geoJson.json" href="#"
|
||||
onclick="exportToGeoJSON(this, JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'))"
|
||||
class="btn btn-default btn-xs" data-toggle="tooltip" data-placement="left"
|
||||
title="Export selected area as a geoJson file">Export</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="setTrafficAlert">
|
||||
<form role="form" style="width: auto;">
|
||||
<div class="form-group">
|
||||
<label class="text-primary" for="areaName">Fence name</label>
|
||||
<input class="form-control" id="areaName" placeholder="Area Name" type="text">
|
||||
<span class="help-block">Name of the selected area(i.e colombo)</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="btn-group btn-group-sm btn-group-justified">
|
||||
<div class="btn-group">
|
||||
<button id="addTrafficAlert" onclick="setTrafficAlert($(this).attr('leaflet_id'))" type="button"
|
||||
class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left"
|
||||
title="Save selected area for alerts">Save
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="editGeoJson"
|
||||
onclick="$('#editTrafficGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editTrafficGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editTrafficGeoJSON').modal('toggle')"
|
||||
type="button" class="btn btn-default btn-xs">Edit
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a id="exportGeoJson" download="geoJson.json" href="#"
|
||||
onclick="exportToGeoJSON(this, JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'))"
|
||||
class="btn btn-default btn-xs" data-toggle="tooltip" data-placement="left"
|
||||
title="Export selected area as a geoJson file">Export</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#zone "bottomJs" }}
|
||||
{{js "js/leaflet/leaflet.js" }}
|
||||
{{js "js/leaflet/leaflet.markercluster.js" }}
|
||||
{{js "js/leaflet/L.Control.Locate.js" }}
|
||||
{{js "js/leaflet/L.Control.Focus.js" }}
|
||||
{{js "js/leaflet/L.Control.GeoAlerts.js" }}
|
||||
{{js "js/leaflet/leaflet.groupedlayercontrol.js" }}
|
||||
{{js "js/leaflet/Leaflet.fullscreen.min.js" }}
|
||||
{{js "js/leaflet/Marker.Rotate.js" }}
|
||||
{{js "js/leaflet/leaflet.draw.js" }}
|
||||
{{js "js/jquery/jquery-ui.min.js" }}
|
||||
<!-- Leaflet plugins libries -->
|
||||
|
||||
{{js "js/firstTemp.js" }}
|
||||
|
||||
{{js "js/typeahead.bundle.min.js" }}
|
||||
|
||||
<!-- C3 charting library using D3 core -->
|
||||
{{js "js/d3/d3.min.js" }}
|
||||
{{js "js/d3/c3.min.js" }}
|
||||
{{js "js/application_options.js" }}
|
||||
{{js "js/secondTemp.js" }}
|
||||
{{js "js/geo_remote.js" }}
|
||||
{{js "js/show_alert_in_map.js" }}
|
||||
{{js "js/app.js" }}
|
||||
{{js "js/websocket.js" }}
|
||||
{{js "js/geo_fencing.js" }}
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
var geoLocationLink = $(".initGeoLocationLink");
|
||||
if (geoLocationLink) {
|
||||
geoLocationLink.on('click', function () {
|
||||
initializeGeoLocation()
|
||||
});
|
||||
{{#if showGeoFencingTools}}
|
||||
var locationItems = geoLocationLink.closest('li');
|
||||
var geoToolsMenu = $("<ul/>", {class: 'collapse list-group geo-tools active'}).appendTo(locationItems);
|
||||
geoPublicUri = $("#geo-charts").data("geo-public-uri");
|
||||
var realtTime = createGeoToolListItem('javascript:enableRealTime()',
|
||||
'Return to Real Time View', 'fw fw-undo', geoToolsMenu);
|
||||
realtTime.css("display", "none");
|
||||
realtTime.attr("id", "realTimeShow");
|
||||
createGeoToolListItem(geoPublicUri + '/assets/html_templates/modal/speed_alert.html',
|
||||
'Set Speed Alert', 'glyphicon glyphicon-dashboard', geoToolsMenu);
|
||||
createGeoToolListItem(geoPublicUri + '/assets/html_templates/modal/stationery_alert.html',
|
||||
'Add Stationary Alert', 'glyphicon glyphicon-link', geoToolsMenu);
|
||||
createGeoToolListItem(geoPublicUri + '/assets/html_templates/modal/within_alert.html',
|
||||
'Add Geo Fence Enter Alert', 'glyphicon glyphicon-log-in', geoToolsMenu);
|
||||
createGeoToolListItem(geoPublicUri + '/assets/html_templates/modal/exit_alert.html',
|
||||
'Add Geo Fence Exit Alert', 'glyphicon glyphicon-log-out', geoToolsMenu);
|
||||
{{/if}}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{{/zone}}
|
||||
|
||||
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
function onRequest(context) {
|
||||
var log = new Log("geo-dashboard.js");
|
||||
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
|
||||
var viewModel = {};
|
||||
|
||||
var carbonServer = require("carbon").server;
|
||||
var device = context.unit.params.device;
|
||||
|
||||
var constants = require("/app/modules/constants.js");
|
||||
var wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/t/";
|
||||
var spatialWSEndpoint = devicemgtProps["wssURL"].replace("https", "wss");
|
||||
var alertsWSEndpoint = devicemgtProps["wssURL"].replace("https", "wss");
|
||||
|
||||
var jwtService = carbonServer.osgiService(
|
||||
'org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService');
|
||||
var jwtClient = jwtService.getJWTClient();
|
||||
var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"]);
|
||||
var token = "";
|
||||
if (encodedClientKeys) {
|
||||
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"];
|
||||
var resp = tokenUtil.decode(encodedClientKeys).split(":");
|
||||
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username, "default", {});
|
||||
if (tokenPair) {
|
||||
token = tokenPair.accessToken;
|
||||
}
|
||||
}
|
||||
viewModel.device = device;
|
||||
viewModel.wsToken = token;
|
||||
viewModel.wsEndpoint = wsEndpoint;
|
||||
if (device.latestDeviceInfo) {
|
||||
viewModel.lastLocation = stringify(device.latestDeviceInfo.location);
|
||||
} else if (device.location) {
|
||||
viewModel.lastLocation = stringify(device.location);
|
||||
} else {
|
||||
viewModel.lastLocation = stringify({});
|
||||
}
|
||||
viewModel.showGeoFencingTools = true;
|
||||
return viewModel;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "1.0.0"
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<div class="modal-header">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h4>
|
||||
Set 'Exit Fence' alerts
|
||||
<br>
|
||||
</h4>
|
||||
</div>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 col-md-8 col-centered">
|
||||
<div class="">
|
||||
<table class="table table-hover" id="exit-alert">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Fence Name</th>
|
||||
<th>Query Name</th>
|
||||
<th>Created On</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<div class="alert alert-info fence-not-exist" role="alert">
|
||||
<strong>Oh snap!</strong> Can't find any geo-fence areas,please draw a new area or try again.
|
||||
</div>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default"
|
||||
onclick="openTools('Exit')">Draw area
|
||||
</button>
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default"
|
||||
onclick="$('#editExitinGeoJSON').modal('toggle')">Enter area
|
||||
</button>
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/devicemgt/public/cdmf.unit.geo-dashboard/js/geo_exit_fence.js"></script>
|
@ -0,0 +1,95 @@
|
||||
<!--~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
~
|
||||
~ WSO2 Inc. licenses this file to you under the Apache License,
|
||||
~ Version 2.0 (the "License"); you may not use this file except
|
||||
~ in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<link href="/portal/store/carbon.super/fs/gadget/geo-dashboard/css/leaflet/L.Grid.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/portal/store/carbon.super/fs/gadget/geo-dashboard/css/main.css" rel="stylesheet" type="text/css"/>
|
||||
<script src="/portal/store/carbon.super/fs/gadget/geo-dashboard/js/leaflet/L.Grid.js"></script>
|
||||
<script src="/portal/store/carbon.super/fs/gadget/geo-dashboard/js/leaflet/L.MeasuringTool.js"></script>
|
||||
<style>
|
||||
.leaflet-grid-label .lng {
|
||||
margin-left: 8px;
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.measuring-line-for-look {
|
||||
stroke-dasharray: 3, 20;
|
||||
}
|
||||
|
||||
.measuring-label-tooltip .leaflet-popup-content-wrapper {
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
opacity: 0.7;
|
||||
padding: 1px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.measuring-label-tooltip .leaflet-popup-content {
|
||||
margin: 0 5px;
|
||||
/*width: 0;*/
|
||||
}
|
||||
|
||||
.measuring-label-tooltip .leaflet-popup-tip-container {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="modal-header"
|
||||
style="cursor: move;background: #f9f9f9;-webkit-box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);-moz-box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">
|
||||
<!-- TODO: Trigger bootstrap tooltip $('#aboutTileUrl').tooltip(); to enable tooltip -->
|
||||
Define proximity
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="proximityMap" style="height: 50%; margin: 0 auto;"></div>
|
||||
<div class="row">
|
||||
<div class="row">
|
||||
<div class="col-md-10 col-md-offset-1">
|
||||
<form class="form-inline" role="form">
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" id="proximityDistance" class="form-control" placeholder="Distance" >
|
||||
<span class="input-group-addon">m</span>
|
||||
</div>
|
||||
<div class="input-group input-group-sm">
|
||||
<input autofocus="enable" id="proximityTime" type="number" class="form-control"
|
||||
placeholder="Close time in S" >
|
||||
<span class="input-group-addon">Seconds</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: -15px" class="btn-group btn-group-justified">
|
||||
<div class="btn-group">
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default"
|
||||
onclick="setProximityAlert()">Set Proximity
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default"
|
||||
onclick="closeAll()">Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/portal/store/carbon.super/fs/gadget/geo-dashboard/js/geo_proximity.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,49 @@
|
||||
<!--~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
~
|
||||
~ WSO2 Inc. licenses this file to you under the Apache License,
|
||||
~ Version 2.0 (the "License"); you may not use this file except
|
||||
~ in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="modal-header">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h4>
|
||||
Setup global speed limit
|
||||
<br>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<div class="input-group input-group-sm">
|
||||
<input autofocus="enable" id="speedAlertValue" type="number" class="form-control" placeholder="Speed alert value " autocomplete="off">
|
||||
<span class="input-group-addon">km/h</span>
|
||||
</div>
|
||||
<br>
|
||||
<button type="button" class="btn btn-default pull-right btn-sm" onclick="closeAll()">Cancel</button>
|
||||
<button type="button" class="btn btn-info pull-right btn-sm" onclick="setSpeedAlert()" style="margin-right: 10px;">Set speed alert</button>
|
||||
<br><br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/devicemgt/public/cdmf.unit.geo-dashboard/js/geo_speed.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,80 @@
|
||||
<!--~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
~
|
||||
~ WSO2 Inc. licenses this file to you under the Apache License,
|
||||
~ Version 2.0 (the "License"); you may not use this file except
|
||||
~ in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style>
|
||||
.fa-trash-o:hover {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="modal-header">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h4>
|
||||
Set 'Stationery' alerts
|
||||
<br>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 col-md-8 col-centered">
|
||||
<div class="">
|
||||
<table class="table table-hover" id="stationary-alert-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Stationery Name</th>
|
||||
<th>Stationery Time</th>
|
||||
<th>Fluctuation Radius</th>
|
||||
<th>Query Name</th>
|
||||
<th>Created On</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<div class="alert alert-info fence-not-exist" role="alert">
|
||||
<strong>Oh snap!</strong> Can't find any geo-fence areas,please draw a new area or try again.
|
||||
</div>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="pull-right">
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default"
|
||||
onclick="openTools('Stationery')">Draw area
|
||||
</button>
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default"
|
||||
onclick="$('#editWithinGeoJSON').modal('toggle')">Enter area
|
||||
</button>
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/devicemgt/public/cdmf.unit.geo-dashboard/js/geo_stationary.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,104 @@
|
||||
<!--~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
~
|
||||
~ WSO2 Inc. licenses this file to you under the Apache License,
|
||||
~ Version 2.0 (the "License"); you may not use this file except
|
||||
~ in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style>
|
||||
.fa-trash-o:hover{color:red;}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
$(".removeGeoFence").tooltip();
|
||||
|
||||
$('.viewGeoFenceRow td:not(:last-child)').click(function () {
|
||||
viewFence(this.parentElement,'Traffic');
|
||||
});
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="modal-header" style="cursor: move;background: #f9f9f9;-webkit-box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);-moz-box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);box-shadow: inset 0px 0px 14px 1px rgba(0,0,0,0.2);">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">
|
||||
<!-- TODO: Trigger bootstrap tooltip $('#aboutTileUrl').tooltip(); to enable tooltip -->
|
||||
Set <i>traffic</i> alerts
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
|
||||
<p class="text-info text-center">View current fences</p>
|
||||
<div class="">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr >
|
||||
<th>Query Name</th>
|
||||
<th>Traffic Congestion Area Name</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<%
|
||||
var alerts = get('traffic');
|
||||
if(alerts){
|
||||
for each(var alert in alerts){
|
||||
%>
|
||||
<tr class="viewGeoFenceRow" style="cursor: pointer" data-areaName='<%= alert.areaName %>' data-queryName='<%= alert.queryName %>' data-geoJson='<%= alert.geoJson %>'>
|
||||
<td><%= alert.queryName %></td>
|
||||
<td><%= alert.areaName %></td>
|
||||
<td onClick="removeGeoFence(this.parentElement,'Traffic')" class="removeGeoFence" data-toggle="tooltip" title="Remove fence" ><i class="fa fa-trash-o"></i></td>
|
||||
</tr>
|
||||
<%
|
||||
}
|
||||
}
|
||||
else{
|
||||
%>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<strong>Oh snap!</strong> Can't find any geo-fence areas,please draw a new area or try again.
|
||||
</div>
|
||||
<%
|
||||
}
|
||||
%>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<p class="text-info text-center">Select Interested Area</p>
|
||||
|
||||
<div style="margin-bottom: -15px" class="btn-group btn-group-justified">
|
||||
<div class="btn-group">
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default" onclick="openTools('Traffic')">Draw area</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default" onclick="$('#editWithinGeoJSON').modal('toggle')" >Enter area</button>
|
||||
</div>
|
||||
<!--<div class="btn-group">-->
|
||||
<!--<button style="background-color: #f4f4f4;" type="button" class="btn btn-default" onclick="closeAll()">Cancel</button>-->
|
||||
<!--</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,47 @@
|
||||
<div class="modal-header">
|
||||
<button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">
|
||||
<div class="col-lg-5 col-md-6 col-centered">
|
||||
<h4>
|
||||
Set 'Within' alerts
|
||||
<br>
|
||||
</h4>
|
||||
</div>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 col-md-8 col-centered">
|
||||
<div class="">
|
||||
<table class="table table-hover" id="within-alert">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Fence Name</th>
|
||||
<th>Query Name</th>
|
||||
<th>Created On</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<div class="alert alert-info fence-not-exist" role="alert">
|
||||
<strong>Oh snap!</strong> Can't find any geo-fence areas,please draw a new area or try again.
|
||||
</div>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default"
|
||||
onclick="openTools('WithIn')">Draw area
|
||||
</button>
|
||||
<button style="background-color: #f4f4f4;" type="button" class="btn btn-default"
|
||||
onclick="$('#editWithinGeoJSON').modal('toggle')">Enter area
|
||||
</button>
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/devicemgt/public/cdmf.unit.geo-dashboard/js/geo_within.js"></script>
|
@ -0,0 +1,52 @@
|
||||
<!--~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
~
|
||||
~ WSO2 Inc. licenses this file to you under the Apache License,
|
||||
~ Version 2.0 (the "License"); you may not use this file except
|
||||
~ in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="viewExitAlert" >
|
||||
<h3 class="popover-title" id="viewAreaName"></h3>
|
||||
<div class="popover-content">
|
||||
<form role="form" style="width: auto" id="exitAlertForm">
|
||||
<button type="button" id="exportGeoJson" download="geoJson.json" onclick="exportToGeoJSON(this,JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'))" class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left" title="Export selected area as a geoJson file">Export</button>
|
||||
<button type="button" id="hideViewFence" class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left" title="Hide this fence" onclick="map.removeLayer(map._layers[$(this).attr('leaflet_id')])" >Hide</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div id="viewWithinAlert" >
|
||||
<h3 class="popover-title" id="viewAreaName"></h3>
|
||||
<div class="popover-content">
|
||||
<form role="form" style="width: auto" class="" id="withinAlertForm">
|
||||
<button type="button" id="exportGeoJson" download="geoJson.json" onclick="exportToGeoJSON(this,JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'))" class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left" title="Export selected area as a geoJson file">Export</button>
|
||||
<button type="button" id="hideViewFence" class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left" title="Hide this fence" onclick="map.removeLayer(map._layers[$(this).attr('leaflet_id')])" >Hide</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div id="viewStationeryAlert" >
|
||||
<h3 class="popover-title" id="viewAreaName"></h3>
|
||||
<div class="popover-content">
|
||||
<form role="form" style="width: auto" id="stationaryAlertForm">
|
||||
<h6>Stationery time(Seconds)<span id="viewAreaTime" class="label label-primary pull-right">N/A</span></h6>
|
||||
<button type="button" id="exportGeoJson" download="geoJson.json" onclick="exportToGeoJSON(this,JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'))" class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left" title="Export selected area as a geoJson file">Export</button>
|
||||
<button type="button" id="hideViewFence" class="btn btn-info btn-xs" data-toggle="tooltip" data-placement="left" title="Hide this fence" onclick="map.removeLayer(map._layers[$(this).attr('leaflet_id')])" >Hide</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,20 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('$executionPlanName')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string);
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string);
|
||||
|
||||
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==false and id == "$deviceId"]#geodashboard:subscribe()
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information
|
||||
insert into dataOut;
|
||||
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=false and id == "$deviceId"]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,140 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('Geo-ExecutionPlan-Proximity_alert')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string );
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut ( id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string );
|
||||
|
||||
@IndexBy('id')
|
||||
define table ProximityTable(id string, timeStamp long);
|
||||
|
||||
@IndexBy('id')
|
||||
define table AlertsTable(id string , proximityWith string, eventId string);
|
||||
|
||||
from dataIn#geodashboard:subscribe()
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId
|
||||
insert into initialStream;
|
||||
|
||||
from initialStream[type == 'STOP']
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from initialStream[type != 'STOP']
|
||||
select *
|
||||
insert into objectInitialStream;
|
||||
|
||||
from objectInitialStream#geo:proximity(id,longitude,latitude, $proximityDistance)
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith
|
||||
insert into proxymityStream;
|
||||
|
||||
from proxymityStream[AlertsTable.id == proxymityStream.id in AlertsTable]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable
|
||||
insert into innerStreamOne;
|
||||
|
||||
from proxymityStream[not(AlertsTable.id == proxymityStream.id in AlertsTable)]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable
|
||||
insert into innerStreamOne;
|
||||
|
||||
from proxymityStream[AlertsTable.id == proxymityStream.proximityWith in AlertsTable]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable
|
||||
insert into innerStreamSeven;
|
||||
|
||||
from proxymityStream[not(AlertsTable.id == proxymityStream.proximityWith in AlertsTable)]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable
|
||||
insert into innerStreamSeven;
|
||||
|
||||
from innerStreamOne[inCloseProximity == true AND not(inAlertTable)]
|
||||
select id,str:concat(",",proximityWith) as proximityWith , eventId
|
||||
insert into AlertsTable;
|
||||
|
||||
from innerStreamSeven[inCloseProximity == true AND not(inAlertTable)]
|
||||
select proximityWith as id,str:concat(",",id) as proximityWith , eventId
|
||||
insert into AlertsTable;
|
||||
|
||||
from innerStreamOne[innerStreamOne.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable
|
||||
on innerStreamOne.id == AlertsTable.id
|
||||
select innerStreamOne.id as id, str:concat(",", innerStreamOne.proximityWith, AlertsTable.proximityWith) as proximityWith, innerStreamOne.eventId as eventId
|
||||
insert into updateStream;
|
||||
|
||||
from innerStreamSeven[innerStreamSeven.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable
|
||||
on innerStreamSeven.proximityWith == AlertsTable.id
|
||||
select innerStreamSeven.proximityWith as id, str:concat(",", innerStreamSeven.id, AlertsTable.proximityWith) as proximityWith, innerStreamSeven.eventId as eventId
|
||||
insert into updateStream;
|
||||
|
||||
from innerStreamOne[innerStreamOne.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable
|
||||
on innerStreamOne.id == AlertsTable.id
|
||||
select innerStreamOne.id as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamOne.proximityWith), "") as proximityWith, innerStreamOne.eventId as eventId
|
||||
insert into updateStream;
|
||||
|
||||
from innerStreamSeven[innerStreamSeven.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable
|
||||
on innerStreamSeven.proximityWith == AlertsTable.id
|
||||
select innerStreamSeven.proximityWith as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamSeven.id), "") as proximityWith, innerStreamSeven.eventId as eventId
|
||||
insert into updateStream;
|
||||
|
||||
from updateStream
|
||||
select *
|
||||
update AlertsTable
|
||||
on id== AlertsTable.id;
|
||||
|
||||
from updateStream[proximityWith == ""]
|
||||
delete AlertsTable
|
||||
on id== AlertsTable.id;
|
||||
|
||||
from objectInitialStream[AlertsTable.id == objectInitialStream.id in AlertsTable]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId, true as inAlertTable
|
||||
insert into publishStream;
|
||||
|
||||
from objectInitialStream[not(AlertsTable.id == objectInitialStream.id in AlertsTable)]
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId, false as inAlertTable
|
||||
insert into publishStream;
|
||||
|
||||
from publishStream[inAlertTable == true]#window.length(0) join AlertsTable
|
||||
on publishStream.id== AlertsTable.id
|
||||
select publishStream.id as id, publishStream.latitude as latitude, publishStream.longitude as longitude, publishStream.timeStamp as timeStamp, publishStream.type as type, publishStream.speed as speed, publishStream.heading as heading, publishStream.eventId as eventId, AlertsTable.proximityWith as proximityInfo
|
||||
insert into innerStreamTwo;
|
||||
|
||||
from publishStream[inAlertTable == false]
|
||||
delete ProximityTable on ProximityTable.id==id;
|
||||
|
||||
from publishStream[inAlertTable == false]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamTwo[ProximityTable.id == innerStreamTwo.id in ProximityTable]
|
||||
insert into innerStreamThree;
|
||||
|
||||
from innerStreamThree#window.length(0) join ProximityTable
|
||||
on innerStreamThree.id == ProximityTable.id
|
||||
select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId, ProximityTable.timeStamp as storedTime, innerStreamThree.proximityInfo as proximityInfo
|
||||
insert into innerStreamFour;
|
||||
|
||||
from innerStreamFour[(timeStamp - storedTime) >= $proximityTime]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,proximityInfo,"true" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamFour[(timeStamp - storedTime) < $proximityTime]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , proximityInfo ,"false" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)]
|
||||
select innerStreamTwo.id, innerStreamTwo.timeStamp
|
||||
insert into ProximityTable;
|
||||
|
||||
from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity
|
||||
insert into dataOutStream;
|
||||
|
||||
from dataOutStream[isProximity == 'true']
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,"WARNING" as state,str:concat("Proximity with "," ",proximityInfo) as information
|
||||
insert into dataOut;
|
||||
|
||||
from dataOutStream[isProximity == 'false']
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,20 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('Geo-ExecutionPlan-Speed---$deviceId_alert')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string);
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string);
|
||||
|
||||
from dataIn[speed >= $speedAlertValue and id == "$deviceId"]#geodashboard:subscribe()
|
||||
select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, "This device movement is not normal!!" as information
|
||||
insert into dataOut;
|
||||
from dataIn[speed < $speedAlertValue and id == "$deviceId"]
|
||||
select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, "This device movement is normal" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,89 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('$executionPlanName')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string);
|
||||
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string);
|
||||
|
||||
@IndexBy('id')
|
||||
define table StationeryTable(id string, timeStamp long);
|
||||
|
||||
@IndexBy('id')
|
||||
define table AlertsTable(id string, stationary bool);
|
||||
|
||||
from dataIn#geodashboard:subscribe()
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,geo:within(longitude,latitude,"$geoFenceGeoJSON") as isWithin
|
||||
insert into innerStreamOne;
|
||||
|
||||
from innerStreamOne[isWithin == false]
|
||||
delete StationeryTable on StationeryTable.id==id;
|
||||
|
||||
from innerStreamOne[isWithin == false]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamOne[isWithin == true]#geo:stationary(id,longitude,latitude, $fluctuationRadius)
|
||||
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,stationary
|
||||
insert into innerStreamTwo;
|
||||
|
||||
from innerStreamTwo[innerStreamTwo.stationary == true]
|
||||
select innerStreamTwo.id, innerStreamTwo.stationary
|
||||
insert into AlertsTable;
|
||||
|
||||
from innerStreamTwo[innerStreamTwo.stationary == false]
|
||||
delete AlertsTable on AlertsTable.id==id;
|
||||
|
||||
from innerStreamTwo[innerStreamTwo.stationary == false]
|
||||
delete StationeryTable on StationeryTable.id==id;
|
||||
|
||||
from innerStreamOne[isWithin == true AND not(AlertsTable.id == innerStreamOne.id in AlertsTable)]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamOne[isWithin == true AND AlertsTable.id == innerStreamOne.id in AlertsTable]
|
||||
insert into innerStreamThree;
|
||||
|
||||
from innerStreamThree#window.length(0) join AlertsTable
|
||||
on innerStreamThree.id == AlertsTable.id
|
||||
select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId
|
||||
insert into innerStreamFour;
|
||||
|
||||
from innerStreamFour[not(StationeryTable.id == innerStreamFour.id in StationeryTable)]
|
||||
select innerStreamFour.id, innerStreamFour.timeStamp
|
||||
insert into StationeryTable;
|
||||
|
||||
from innerStreamOne[isWithin == true AND not(StationeryTable.id == innerStreamOne.id in StationeryTable)]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamOne[isWithin == true AND StationeryTable.id == innerStreamOne.id in StationeryTable]
|
||||
insert into innerStreamFive;
|
||||
|
||||
from innerStreamFive#window.length(0) join StationeryTable
|
||||
on innerStreamFive.id == StationeryTable.id
|
||||
select innerStreamFive.id , innerStreamFive.latitude, innerStreamFive.longitude,innerStreamFive.timeStamp, innerStreamFive.type, innerStreamFive.speed, innerStreamFive.heading ,innerStreamFive.eventId, StationeryTable.timeStamp as storedTime
|
||||
insert into innerStreamSix;
|
||||
|
||||
from innerStreamSix[(timeStamp - storedTime) >= $stationeryTime]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"true" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from innerStreamSix[(timeStamp - storedTime) < $stationeryTime]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"false" as isStationary
|
||||
insert into dataOutStream;
|
||||
|
||||
from dataOutStream[isStationary == 'true']
|
||||
select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, "This device is in $stationeryName area!!!" as information
|
||||
insert into dataOut;
|
||||
|
||||
from dataOutStream[isStationary == 'false']
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,17 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('$executionPlanName')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('rawGeoStream:1.0.0')
|
||||
define stream dataIn (id string, timeStamp long, geometry string, state string, information string);
|
||||
|
||||
@Export('AlertsNotifications:1.0.0')
|
||||
define stream dataOut (id string, state string, information string, timeStamp long, latitude double, longitude double);
|
||||
|
||||
from dataIn[geo:intersects(geometry, "$geoFenceGeoJSON")==true and geodashboard:needToNotify(id, str:concat(information, state), "sendFirst") == true and id == $deviceId]
|
||||
select id, state, str:concat("Traffic alert in $areaName. State: ", state, " ", information) as information, timeStamp, 0.0 as latitude, 0.0 as longitude
|
||||
insert into dataOut
|
@ -0,0 +1,20 @@
|
||||
/* Enter a unique ExecutionPlan */
|
||||
@Plan:name('$executionPlanName')
|
||||
|
||||
/* Enter a unique description for ExecutionPlan */
|
||||
-- @Plan:description('ExecutionPlan')
|
||||
|
||||
/* define streams/tables and write queries here ... */
|
||||
|
||||
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
|
||||
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string);
|
||||
|
||||
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
|
||||
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string);
|
||||
|
||||
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==true and id == "$deviceId"]#geodashboard:subscribe()
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information
|
||||
insert into dataOut;
|
||||
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=true and id == "$deviceId"]
|
||||
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information
|
||||
insert into dataOut;
|
@ -0,0 +1,31 @@
|
||||
/* Compatible with Leaflet 0.7 */
|
||||
|
||||
@import url('font/locate-fa.woff');
|
||||
@import url('css/locate-fa.css');
|
||||
@import url('css/animation.css');
|
||||
|
||||
.leaflet-touch .leaflet-bar-part-single {
|
||||
-webkit-border-radius: 7px 7px 7px 7px;
|
||||
border-radius: 7px 7px 7px 7px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.leaflet-control-locate a {
|
||||
font-size: 1.4em;
|
||||
margin-left: 1px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.leaflet-control-locate.active a {
|
||||
color: #2074B6;
|
||||
}
|
||||
|
||||
.leaflet-control-locate.active.following a {
|
||||
color: #FC8428;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-locate {
|
||||
box-shadow: none;
|
||||
border: 2px solid rgba(0,0,0,0.2);
|
||||
background-clip: padding-box;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
/* Conditional stylesheet for IE. */
|
||||
@import url('css/locate-fa-ie7.css');
|
||||
|
||||
.leaflet-control-locate {
|
||||
border: 3px solid #999;
|
||||
}
|
||||
|
||||
.leaflet-control-locate a {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.leaflet-control-locate a:hover {
|
||||
background-color: #fff;
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
.marker-cluster-small {
|
||||
background-color: rgba(181, 226, 140, 0.6);
|
||||
}
|
||||
.marker-cluster-small div {
|
||||
background-color: rgba(110, 204, 57, 0.6);
|
||||
}
|
||||
|
||||
.marker-cluster-medium {
|
||||
background-color: rgba(241, 211, 87, 0.6);
|
||||
}
|
||||
.marker-cluster-medium div {
|
||||
background-color: rgba(240, 194, 12, 0.6);
|
||||
}
|
||||
|
||||
.marker-cluster-large {
|
||||
background-color: rgba(253, 156, 115, 0.6);
|
||||
}
|
||||
.marker-cluster-large div {
|
||||
background-color: rgba(241, 128, 23, 0.6);
|
||||
}
|
||||
|
||||
/* IE 6-8 fallback colors */
|
||||
.leaflet-oldie .marker-cluster-small {
|
||||
background-color: rgb(181, 226, 140);
|
||||
}
|
||||
.leaflet-oldie .marker-cluster-small div {
|
||||
background-color: rgb(110, 204, 57);
|
||||
}
|
||||
|
||||
.leaflet-oldie .marker-cluster-medium {
|
||||
background-color: rgb(241, 211, 87);
|
||||
}
|
||||
.leaflet-oldie .marker-cluster-medium div {
|
||||
background-color: rgb(240, 194, 12);
|
||||
}
|
||||
|
||||
.leaflet-oldie .marker-cluster-large {
|
||||
background-color: rgb(253, 156, 115);
|
||||
}
|
||||
.leaflet-oldie .marker-cluster-large div {
|
||||
background-color: rgb(241, 128, 23);
|
||||
}
|
||||
|
||||
.marker-cluster {
|
||||
background-clip: padding-box;
|
||||
border-radius: 20px;
|
||||
}
|
||||
.marker-cluster div {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-left: 5px;
|
||||
margin-top: 5px;
|
||||
|
||||
text-align: center;
|
||||
border-radius: 15px;
|
||||
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
.marker-cluster span {
|
||||
line-height: 30px;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
|
||||
-webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
-moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
-o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
transition: transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
input[type="radio"], input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
.map-wrapper{
|
||||
background: #37474f;
|
||||
}
|
||||
#left_side_pannel> .nav > li > a{
|
||||
color: #fff;
|
||||
}
|
||||
.typeahead {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
#map {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
}
|
||||
#loading {
|
||||
position: absolute;
|
||||
width: 220px;
|
||||
height: 19px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -10px 0 0 -110px;
|
||||
z-index: 20001;
|
||||
}
|
||||
/*.sidebar-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.sidebar-table {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 124px;
|
||||
bottom: 0px;
|
||||
overflow: auto;
|
||||
}*/
|
||||
.leaflet-control-layers label {
|
||||
font-weight: normal;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.leaflet-control-layers-group-name {
|
||||
font-weight: bold;
|
||||
margin-bottom: .2em;
|
||||
display: block;
|
||||
}
|
||||
.leaflet-control-layers-group {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
.leaflet-control-layers-group label {
|
||||
padding-left: .5em;
|
||||
}
|
||||
.table {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.tt-dropdown-menu {
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
margin-top: 4px;
|
||||
padding: 4px 0;
|
||||
width: 100%;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
.tt-suggestion {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
padding: 3px 10px;
|
||||
}
|
||||
.tt-suggestion.tt-cursor {
|
||||
background-color: #0097CF;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tt-suggestion p {
|
||||
margin: 0;
|
||||
}
|
||||
.tt-suggestion + .tt-suggestion {
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
.typeahead-header {
|
||||
margin: 0 5px 5px 5px;
|
||||
padding: 3px 0;
|
||||
border-bottom: 2px solid #333;
|
||||
}
|
||||
.has-feedback .form-control-feedback {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: block;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
/*.navbar .navbar-brand {
|
||||
font-size: 18px;
|
||||
}*/
|
||||
}
|
||||
@media (max-width: 767px){
|
||||
.url-break {
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
#sidebar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.leaflet-geo-alerts{
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
background-color: white;
|
||||
padding: 5px;
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
width: 200px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.leaflet-geo-alerts a{
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
!* Print Handling *!
|
||||
@media print {
|
||||
.navbar {
|
||||
display: none !important;
|
||||
}
|
||||
.leaflet-control-container {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.nav > li > a {
|
||||
padding: 25px 15px !important;
|
||||
}
|
||||
|
||||
.nav > li > a:hover, .nav > li > a:focus {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
*/
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2013 Panopta, Andrew Moffat
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,182 @@
|
||||
/* WIZARD GENERAL */
|
||||
.wizard {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.wizard-dialog {}
|
||||
.wizard-content {}
|
||||
|
||||
.wizard-body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* WIZARD HEADER */
|
||||
.wizard-header {
|
||||
padding: 9px 15px;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.wizard-header h3 {
|
||||
margin: 0;
|
||||
line-height: 35px;
|
||||
display: inline;
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
font-family: inherit;
|
||||
font-weight: bold;
|
||||
text-rendering: optimizelegibility;
|
||||
color: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.wizard-subtitle {
|
||||
font-weight:bold;
|
||||
color:#AFAFAF;
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
|
||||
/* WIZARD NAVIGATION */
|
||||
.wizard-steps {
|
||||
width: 28%;
|
||||
background-color: #f5f5f5;
|
||||
border-bottom-left-radius: 6px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wizard-nav-container {
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.wizard-nav-list {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.wizard-nav-link .glyphicon-chevron-right {
|
||||
float:right;
|
||||
margin-top:12px;
|
||||
margin-right:-6px;
|
||||
opacity:.25;
|
||||
}
|
||||
|
||||
li.wizard-nav-item.active .glyphicon-chevron-right {
|
||||
opacity:1;
|
||||
}
|
||||
|
||||
li.wizard-nav-item {
|
||||
line-height:40px;
|
||||
}
|
||||
|
||||
.wizard-nav-list > li > a {
|
||||
background-color:#f5f5f5;
|
||||
padding:3px 15px 3px 20px;
|
||||
cursor:default;
|
||||
color:#B4B4B4;
|
||||
}
|
||||
|
||||
.wizard-nav-list > li > a:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.wizard-nav-list > li.already-visited > a.wizard-nav-link {
|
||||
color:#08C;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.wizard-nav-list > li.active > a.wizard-nav-link {
|
||||
color:white;
|
||||
}
|
||||
|
||||
.wizard-nav-item .already-visited .active {
|
||||
background-color:#08C;
|
||||
}
|
||||
|
||||
.wizard-nav-list li.active > a {
|
||||
background-color:#08C;
|
||||
}
|
||||
|
||||
|
||||
/* WIZARD CONTENT */
|
||||
.wizard-body form {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* WIZARD PROGRESS BAR */
|
||||
.wizard-progress-container {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.wizard-card-container {
|
||||
margin-left: 28%;
|
||||
}
|
||||
|
||||
/* WIZARD CARDS */
|
||||
.wizard-error,
|
||||
.wizard-failure,
|
||||
.wizard-success,
|
||||
.wizard-loading,
|
||||
.wizard-card {
|
||||
border-top: 1px solid #EEE;
|
||||
display:none;
|
||||
padding:35px;
|
||||
padding-top:20px;
|
||||
overflow-y:auto;
|
||||
|
||||
/*
|
||||
position:relative;
|
||||
height:300px;
|
||||
margin-right: 5px;
|
||||
*/
|
||||
}
|
||||
|
||||
.wizard-card-overlay {
|
||||
overflow-y: initial;
|
||||
}
|
||||
|
||||
.wizard-card > h3 {
|
||||
margin-top:0;
|
||||
margin-bottom:20px;
|
||||
font-size:21px;
|
||||
line-height:40px;
|
||||
font-weight:normal;
|
||||
}
|
||||
|
||||
/* WIZARD FOOTER */
|
||||
.wizard-footer {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.wizard-buttons-container {
|
||||
padding:20px;
|
||||
}
|
||||
|
||||
.wizard-cancel {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
/* Inner Card */
|
||||
.wizard-input-section {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
.wizard-dialog .popover.error-popover {
|
||||
background-color:#F2DEDE;
|
||||
color:#B94A48;
|
||||
border-color:#953B39;
|
||||
}
|
||||
|
||||
.wizard-dialog .popover.error-popover .arrow::after {
|
||||
border-right-color:#F2DEDE;
|
||||
}
|
||||
|
||||
.wizard-dialog .popover.error-popover .popover-title {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.wizard-dialog .popover.error-popover .arrow {
|
||||
border-right-color:#953B39;
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Animation example, for spinners
|
||||
*/
|
||||
.animate-spin:before {
|
||||
-moz-animation: spin 2s infinite linear;
|
||||
-o-animation: spin 2s infinite linear;
|
||||
-webkit-animation: spin 2s infinite linear;
|
||||
animation: spin 2s infinite linear;
|
||||
display: inline-block;
|
||||
}
|
||||
@-moz-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-o-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-ms-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
|
||||
.icon-location:before { content: '\e802'; } /* '' */
|
||||
.icon-direction:before { content: '\e800'; } /* '' */
|
||||
.icon-spinner:before { content: '\e801'; } /* '' */
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,4 @@
|
||||
|
||||
.icon-location { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-direction { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
@ -0,0 +1,15 @@
|
||||
[class^="icon-"], [class*=" icon-"] {
|
||||
font-family: 'locate-fa';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
|
||||
/* fix buttons height */
|
||||
line-height: 1em;
|
||||
|
||||
/* you can be more comfortable with increased icons size */
|
||||
/* font-size: 120%; */
|
||||
}
|
||||
|
||||
.icon-location { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-direction { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
@ -0,0 +1,72 @@
|
||||
@font-face {
|
||||
font-family: 'locate-fa';
|
||||
src: url('../font/locate-fa.eot?9201824');
|
||||
src: url('../font/locate-fa.eot?9201824#iefix') format('embedded-opentype'),
|
||||
url('../font/locate-fa.woff?9201824') format('woff'),
|
||||
url('../font/locate-fa.ttf?9201824') format('truetype'),
|
||||
url('../font/locate-fa.svg?9201824#locate-fa') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
/* use SVG only on mobile devices to avoid display issue on android
|
||||
issue: https://github.com/domoritz/leaflet-locatecontrol/issues/78
|
||||
solution: http://stackoverflow.com/a/21050160/1106908
|
||||
*/
|
||||
@media only screen and (max-width: 320px),
|
||||
screen and (max-device-width: 720px) and (orientation: portrait),
|
||||
screen and (max-device-width: 1280px) and (orientation: landscape)
|
||||
{
|
||||
@font-face {
|
||||
font-family: 'locate-fa';
|
||||
src: url('../font/locate-fa.eot?9201824');
|
||||
src: url('../font/locate-fa.svg?9201824#locate-fa') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
|
||||
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
|
||||
/*
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
@font-face {
|
||||
font-family: 'locate-fa';
|
||||
src: url('../font/locate-fa.svg?9201824#locate-fa') format('svg');
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
[class^="icon-"]:before, [class*=" icon-"]:before {
|
||||
font-family: "locate-fa";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
speak: none;
|
||||
|
||||
display: inline-block;
|
||||
text-decoration: inherit;
|
||||
width: 1em;
|
||||
margin-right: .2em;
|
||||
text-align: center;
|
||||
/* opacity: .8; */
|
||||
|
||||
/* For safety - reset parent styles, that can break glyph codes*/
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
|
||||
/* fix buttons height, for twitter bootstrap */
|
||||
line-height: 1em;
|
||||
|
||||
/* Animation center compensation - margins should be symmetric */
|
||||
/* remove if not needed */
|
||||
margin-left: .2em;
|
||||
|
||||
/* you can be more comfortable with increased icons size */
|
||||
/* font-size: 120%; */
|
||||
|
||||
/* Uncomment for 3D effect */
|
||||
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
|
||||
}
|
||||
|
||||
.icon-location:before { content: '\e802'; } /* '' */
|
||||
.icon-direction:before { content: '\e800'; } /* '' */
|
||||
.icon-spinner:before { content: '\e801'; } /* '' */
|
@ -0,0 +1,203 @@
|
||||
/*-- Chart --*/
|
||||
|
||||
.c3 svg {
|
||||
font: 10px sans-serif;
|
||||
}
|
||||
.c3 path, .c3 line {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
}
|
||||
.c3 text {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.c3-legend-item-tile,
|
||||
.c3-xgrid-focus,
|
||||
.c3-ygrid,
|
||||
.c3-event-rect,
|
||||
.c3-bars path {
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.c3-chart-arc path {
|
||||
stroke: #fff;
|
||||
|
||||
}
|
||||
.c3-chart-arc text {
|
||||
fill: #fff;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/*-- Axis --*/
|
||||
|
||||
.c3-axis-x .tick {
|
||||
}
|
||||
.c3-axis-x-label {
|
||||
}
|
||||
|
||||
.c3-axis-y .tick {
|
||||
}
|
||||
.c3-axis-y-label {
|
||||
}
|
||||
|
||||
.c3-axis-y2 .tick {
|
||||
}
|
||||
.c3-axis-y2-label {
|
||||
}
|
||||
|
||||
/*-- Grid --*/
|
||||
|
||||
.c3-grid line {
|
||||
stroke: #aaa;
|
||||
}
|
||||
.c3-grid text {
|
||||
fill: #aaa;
|
||||
}
|
||||
.c3-xgrid, .c3-ygrid {
|
||||
stroke-dasharray: 3 3;
|
||||
}
|
||||
.c3-xgrid-focus {
|
||||
}
|
||||
|
||||
/*-- Text on Chart --*/
|
||||
|
||||
.c3-text {
|
||||
}
|
||||
|
||||
.c3-text.c3-empty {
|
||||
fill: #808080;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
/*-- Line --*/
|
||||
|
||||
.c3-line {
|
||||
stroke-width: 1px;
|
||||
}
|
||||
/*-- Point --*/
|
||||
|
||||
.c3-circle._expanded_ {
|
||||
stroke-width: 1px;
|
||||
stroke: white;
|
||||
}
|
||||
.c3-selected-circle {
|
||||
fill: white;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
/*-- Bar --*/
|
||||
|
||||
.c3-bar {
|
||||
stroke-width: 0;
|
||||
}
|
||||
.c3-bar._expanded_ {
|
||||
fill-opacity: 0.75;
|
||||
}
|
||||
|
||||
/*-- Arc --*/
|
||||
|
||||
.c3-chart-arcs-title {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
/*-- Focus --*/
|
||||
|
||||
.c3-target.c3-focused path.c3-line, .c3-target.c3-focused path.c3-step {
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
/*-- Region --*/
|
||||
|
||||
.c3-region {
|
||||
fill: steelblue;
|
||||
fill-opacity: .1;
|
||||
}
|
||||
|
||||
/*-- Brush --*/
|
||||
|
||||
.c3-brush .extent {
|
||||
fill-opacity: .1;
|
||||
}
|
||||
|
||||
/*-- Select - Drag --*/
|
||||
|
||||
.c3-dragarea {
|
||||
}
|
||||
|
||||
/*-- Legend --*/
|
||||
|
||||
.c3-legend-item {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.c3-legend-background {
|
||||
opacity: 0.75;
|
||||
fill: white;
|
||||
stroke: lightgray;
|
||||
stroke-width: 1
|
||||
}
|
||||
|
||||
/*-- Tooltip --*/
|
||||
|
||||
.c3-tooltip {
|
||||
border-collapse:collapse;
|
||||
border-spacing:0;
|
||||
background-color:#fff;
|
||||
empty-cells:show;
|
||||
-webkit-box-shadow: 7px 7px 12px -9px rgb(119,119,119);
|
||||
-moz-box-shadow: 7px 7px 12px -9px rgb(119,119,119);
|
||||
box-shadow: 7px 7px 12px -9px rgb(119,119,119);
|
||||
opacity: 0.9;
|
||||
}
|
||||
.c3-tooltip tr {
|
||||
border:1px solid #CCC;
|
||||
}
|
||||
.c3-tooltip th {
|
||||
background-color: #aaa;
|
||||
font-size:14px;
|
||||
padding:2px 5px;
|
||||
text-align:left;
|
||||
color:#FFF;
|
||||
}
|
||||
.c3-tooltip td {
|
||||
font-size:13px;
|
||||
padding: 3px 6px;
|
||||
background-color:#fff;
|
||||
border-left:1px dotted #999;
|
||||
}
|
||||
.c3-tooltip td > span {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
.c3-tooltip td.value{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.c3-area {
|
||||
stroke-width: 0;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.c3-chart-arcs .c3-chart-arcs-background {
|
||||
fill: #e0e0e0;
|
||||
stroke: none;
|
||||
}
|
||||
.c3-chart-arcs .c3-chart-arcs-gauge-unit {
|
||||
fill: #000;
|
||||
font-size: 16px;
|
||||
}
|
||||
.c3-chart-arcs .c3-chart-arcs-gauge-max {
|
||||
fill: #777;
|
||||
}
|
||||
.c3-chart-arcs .c3-chart-arcs-gauge-min {
|
||||
fill: #777;
|
||||
}
|
||||
|
||||
.c3-chart-arc .c3-gauge-value {
|
||||
fill: #000;
|
||||
font-size: 28px;
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,10 @@
|
||||
Font license info
|
||||
|
||||
|
||||
## Font Awesome
|
||||
|
||||
Copyright (C) 2012 by Dave Gandy
|
||||
|
||||
Author: Dave Gandy
|
||||
License: SIL ()
|
||||
Homepage: http://fortawesome.github.com/Font-Awesome/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue