diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java index b2088f5ba5e..23602baf0c4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java @@ -232,7 +232,7 @@ public interface GeoLocationBasedService { /** * Create Geo alerts - */ + */ @POST @Path("alerts/{alertType}/{deviceType}/{deviceId}") @ApiOperation( @@ -297,7 +297,7 @@ public interface GeoLocationBasedService { /** - * Create Geo alerts for geo-dashboard + * Create Geo alerts for geo clusters */ @POST @Path("/alerts/{alertType}") @@ -305,7 +305,7 @@ public interface GeoLocationBasedService { consumes = "application/json", produces = "application/json", httpMethod = "POST", - value = "Create Geo alerts for the device", + value = "Create Geo alerts for geo clusters", notes = "", response = Response.class, tags = "Geo Service Management", @@ -337,7 +337,7 @@ public interface GeoLocationBasedService { message = "Internal Server Error. \n Error on retrieving stats", response = Response.class) }) - Response createGeoAlertsForGeoDashboard( + Response createGeoAlertsForGeoClusters( @ApiParam( name = "alert", value = "The alert object", @@ -414,6 +414,59 @@ public interface GeoLocationBasedService { required = true) @PathParam("alertType") String alertType); + /** + * Update Geo alerts for geo clusters + */ + @PUT + @Path("alerts/{alertType}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Update Geo alerts for geo clusters", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:alerts-manage") + }) + } + ) + @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 updateGeoAlertsForGeoClusters( + @ApiParam( + name = "alert", + value = "The alert object", + required = true) + @Valid Alert alert, + @ApiParam( + name = "alertType", + value = "The alert type, such as Within, Speed, Stationary", + required = true) + @PathParam("alertType") String alertType); + /** * Retrieve Geo alerts */ @@ -478,6 +531,59 @@ public interface GeoLocationBasedService { required = true) @PathParam("alertType") String alertType); + /** + * Retrieve Geo alerts for geo clusters + */ + @GET + @Path("alerts/{alertType}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Retrieve Geo alerts for geo clusters", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:alerts-manage") + }) + } + ) + @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 getGeoAlertsForGeoClusters( + @ApiParam( + name = "alertType", + value = "The alert type, such as Within, Speed, Stationary", + required = true) + @PathParam("alertType") String alertType); + + /** * Retrieve Geo alerts history */ @@ -547,6 +653,68 @@ public interface GeoLocationBasedService { required = true) @QueryParam("to") long to); + /** + * Retrieve Geo alerts history for geo clusters + */ + @GET + @Path("alerts/history") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Retrieve Geo alerts history for geo clusters", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:alerts-manage") + }) + } + ) + @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 getGeoAlertsHistoryForGeoClusters( + @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); + + + /** + * Remove geo alerts + */ + @DELETE @Path("alerts/{alertType}/{deviceType}/{deviceId}") @ApiOperation( @@ -607,5 +775,59 @@ public interface GeoLocationBasedService { " here.", required = true) @QueryParam("queryName") String queryName); + + /** + * Remove geo alerts for geo clusters + */ + + @DELETE + @Path("alerts/{alertType}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "DELETE", + value = "Deletes Geo alerts for the device", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:alerts-manage") + }) + } + ) + @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 removeGeoAlertsForGeoClusters( + @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); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java index 7890b463fcf..c5c96263b92 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java @@ -190,7 +190,7 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { @POST @Consumes("application/json") @Produces("application/json") - public Response createGeoAlertsForGeoDashboard(Alert alert, @PathParam("alertType") String alertType) { + public Response createGeoAlertsForGeoClusters(Alert alert, @PathParam("alertType") String alertType) { try { // this is the user who initiates the request String authorizedUser = MultitenantUtils.getTenantAwareUsername( @@ -245,6 +245,27 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } } + @Path("alerts/{alertType}") + @PUT + @Consumes("application/json") + @Produces("application/json") + public Response updateGeoAlertsForGeoClusters(Alert alert, @PathParam("alertType") String alertType) { + try { + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); + geoService.updateGeoAlert(alert, alertType); + return Response.ok().build(); + } catch (GeoLocationBasedServiceException e) { + String error = "Error occurred while updating the geo alert for geo clusters"; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Path("alerts/{alertType}/{deviceType}/{deviceId}") @DELETE @Consumes("application/json") @@ -279,6 +300,27 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } } + @Path("alerts/{alertType}") + @DELETE + @Consumes("application/json") + @Produces("application/json") + public Response removeGeoAlertsForGeoClusters(@PathParam("alertType") String alertType, @QueryParam("queryName") String queryName) { + try { + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); + geoService.removeGeoAlert(alertType, queryName); + return Response.ok().build(); + } catch (GeoLocationBasedServiceException e) { + String error = "Error occurred while removing the geo alert for geo clusters"; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Path("alerts/{alertType}/{deviceType}/{deviceId}") @GET @Consumes("application/json") @@ -331,6 +373,47 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } } + @Path("alerts/{alertType}") + @GET + @Consumes("application/json") + @Produces("application/json") + public Response getGeoAlertsForGeoClusters(@PathParam("alertType") String alertType) { + try { + + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); + + if (GeoServices.ALERT_TYPE_WITHIN.equals(alertType)) { + List alerts = geoService.getWithinAlerts(); + return Response.ok().entity(alerts).build(); + } else if (GeoServices.ALERT_TYPE_EXIT.equals(alertType)) { + List alerts = geoService.getExitAlerts(); + return Response.ok().entity(alerts).build(); + } else if (GeoServices.ALERT_TYPE_SPEED.equals(alertType)) { + String result = geoService.getSpeedAlerts(); + return Response.ok().entity(result).build(); + } else if (GeoServices.ALERT_TYPE_PROXIMITY.equals(alertType)) { + String result = geoService.getProximityAlerts(); + return Response.ok().entity(result).build(); + } else if (GeoServices.ALERT_TYPE_STATIONARY.equals(alertType)) { + List alerts = geoService.getStationaryAlerts(); + return Response.ok().entity(alerts).build(); + } else if (GeoServices.ALERT_TYPE_TRAFFIC.equals(alertType)) { + List alerts = geoService.getTrafficAlerts(); + return Response.ok().entity(alerts).build(); + } + return null; + } catch (GeoLocationBasedServiceException e) { + String error = "Error occurred while getting the geo alerts for " + alertType + "alert"; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Path("alerts/history/{deviceType}/{deviceId}") @GET @Consumes("application/json") @@ -381,6 +464,49 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } } + @Path("alerts/history") + @GET + @Consumes("application/json") + @Produces("application/json") + public Response getGeoAlertsHistoryForGeoClusters(@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 = ""; + if (from != 0 || to != 0) { + query = "timeStamp : [" + fromDate + " TO " + toDate + "]"; + } + try { + List 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 searchResults = analyticsDataAPI.search(tenantId, tableName, query, + 0, + 100, + sortByFields); + List events = getEventBeans(analyticsDataAPI, tenantId, tableName, new ArrayList(), + 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 (Exception e) { + log.error(e.getMessage()); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); + } + } + private List getEventBeans(AnalyticsDataAPI analyticsDataAPI, int tenantId, String tableName, List columns, List searchResults) throws AnalyticsException { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java index 924f385dd38..47daac0492a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java @@ -30,8 +30,12 @@ public interface GeoLocationProviderService { List getWithinAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + List getWithinAlerts() throws GeoLocationBasedServiceException; + List getExitAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + List getExitAlerts() throws GeoLocationBasedServiceException; + boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException; @@ -41,14 +45,28 @@ public interface GeoLocationProviderService { boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException; + boolean updateGeoAlert(Alert alert, String alertType) + throws GeoLocationBasedServiceException; + boolean removeGeoAlert(String alertType, DeviceIdentifier identifier, String queryName) throws GeoLocationBasedServiceException; + boolean removeGeoAlert(String alertType, String queryName) + throws GeoLocationBasedServiceException; + String getSpeedAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + String getSpeedAlerts() throws GeoLocationBasedServiceException; + String getProximityAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + String getProximityAlerts() throws GeoLocationBasedServiceException; + List getStationaryAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + List getStationaryAlerts() throws GeoLocationBasedServiceException; + List getTrafficAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + + List getTrafficAlerts() throws GeoLocationBasedServiceException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java index 39cd9e71ddc..7174bea0ae5 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java @@ -159,6 +159,53 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public List getWithinAlerts() throws GeoLocationBasedServiceException { + + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_WITHIN; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List 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 GeoLocationBasedServiceException( + "Error occurred while getting the geo alerts" , e); + } + } + @Override public List getExitAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException { @@ -207,6 +254,53 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public List getExitAlerts() throws GeoLocationBasedServiceException { + + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_EXIT; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List 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 GeoLocationBasedServiceException( + "Error occurred while getting the geo alerts", e); + } + } + @Override public boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException { @@ -225,6 +319,12 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic return saveGeoAlert(alert, identifier, alertType, true); } + @Override + public boolean updateGeoAlert(Alert alert, String alertType) + throws GeoLocationBasedServiceException { + return saveGeoAlert(alert, alertType, true); + } + public boolean saveGeoAlert(Alert alert, String alertType, boolean isUpdate) throws GeoLocationBasedServiceException { @@ -277,11 +377,16 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic String action = (isUpdate ? "updating" : "creating"); try { eventprocessorStub = getEventProcessorAdminServiceStub(); - String parsedTemplate = parseTemplateForDeviceClusters(alertType, parseMap); + String parsedTemplate = parseTemplateForGeoClusters(alertType, parseMap); String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate); if (validationResponse.equals("success")) { if (isUpdate) { String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName()); + try { + String existingPlanName = eventprocessorStub.getActiveExecutionPlan(executionPlanName); + } catch (Exception e) { + eventprocessorStub.deployExecutionPlan(parsedTemplate); + } eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); } else { eventprocessorStub.deployExecutionPlan(parsedTemplate); @@ -498,7 +603,10 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic if ("Traffic".equals(alertType)) { return "Geo-ExecutionPlan-Traffic_" + queryName + "_alert"; } else { - return "Geo-ExecutionPlan-" + alertType + "_" + queryName + "---_" + "_alert"; + if (alertType.equals("Speed")) { + return "Geo-ExecutionPlan-" + alertType + "---" + "_alert"; + } + return "Geo-ExecutionPlan-" + alertType + "_" + queryName + "---" + "_alert"; } } @@ -530,6 +638,32 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public boolean removeGeoAlert(String alertType, String queryName) + throws GeoLocationBasedServiceException { + removeFromRegistry(alertType, queryName); + String executionPlanName = getExecutionPlanName(alertType, queryName); + EventProcessorAdminServiceStub eventprocessorStub = null; + try { + eventprocessorStub = getEventProcessorAdminServiceStub(); + eventprocessorStub.undeployActiveExecutionPlan(executionPlanName); + return true; + } catch (IOException e) { + throw new GeoLocationBasedServiceException( + "Event processor admin service stub invocation failed while removing geo alert '" + + alertType + + "': " + executionPlanName, e + ); + } catch (JWTClientException e) { + throw new GeoLocationBasedServiceException( + "JWT token creation failed while removing geo alert '" + alertType + "': " + + executionPlanName, e + ); + } finally { + cleanup(eventprocessorStub); + } + } + private void removeFromRegistry(String alertType, DeviceIdentifier identifier, String queryName) throws GeoLocationBasedServiceException { String path = "unknown"; @@ -543,6 +677,18 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + private void removeFromRegistry(String alertType, String queryName) + throws GeoLocationBasedServiceException { + String path = "unknown"; + try { + path = getRegistryPath(alertType, queryName); + getGovernanceRegistry().delete(path); + } catch (RegistryException e) { + throw new GeoLocationBasedServiceException( + "Error occurred while removing " + alertType + " alert " + " from the path: " + path); + } + } + protected EventProcessorAdminServiceStub getEventProcessorAdminServiceStub() throws JWTClientException { //send alert to event-processing String eventProcessorAdminServiceWSUrl = Utils.replaceSystemProperty(GeoServices.DAS_URL) + @@ -607,6 +753,24 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public String getSpeedAlerts() throws GeoLocationBasedServiceException { + try { + Registry registry = getGovernanceRegistry(); + Resource resource = registry.get(GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_SPEED); + 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 GeoLocationBasedServiceException { try { @@ -631,6 +795,30 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public String getProximityAlerts() throws GeoLocationBasedServiceException { + try { + Registry registry = getGovernanceRegistry(); + Resource resource = registry.get(GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_PROXIMITY); + 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 getStationaryAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException { @@ -683,6 +871,57 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public List getStationaryAlerts() throws GeoLocationBasedServiceException { + + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_STATIONARY; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List 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 GeoLocationBasedServiceException( + "Error occurred while getting the geo alerts", e); + } + } + @Override public List getTrafficAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException { Registry registry = getGovernanceRegistry(); @@ -730,6 +969,52 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public List getTrafficAlerts() throws GeoLocationBasedServiceException { + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_STATIONARY; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List 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 GeoLocationBasedServiceException( + "Error occurred while getting the geo alerts", e); + } + } + private Registry getGovernanceRegistry() throws GeoLocationBasedServiceException { try { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); @@ -765,9 +1050,9 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } - private String parseTemplateForDeviceClusters(String alertType, Map parseMap) throws + private String parseTemplateForGeoClusters(String alertType, Map parseMap) throws GeoLocationBasedServiceException { - String templatePath = "alerts/Geo-ExecutionPlan-" + alertType + "_alert_for_deviceClusters.siddhiql"; + String templatePath = "alerts/Geo-ExecutionPlan-" + alertType + "_alert_for_GeoClusters.siddhiql"; InputStream resource = getClass().getClassLoader().getResourceAsStream(templatePath); if (resource == null) { throw new GeoLocationBasedServiceException("Could not find template in path : " + templatePath); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql similarity index 100% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_deviceClusters.siddhiql rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert_for_GeoClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert_for_GeoClusters.siddhiql new file mode 100644 index 00000000000..fb64720391a --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert_for_GeoClusters.siddhiql @@ -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; \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql similarity index 100% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_deviceClusters.siddhiql rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql new file mode 100644 index 00000000000..46bfbfe2e35 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql @@ -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; \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_GeoClusters.siddhiql similarity index 100% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_deviceClusters.siddhiql rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_GeoClusters.siddhiql diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql similarity index 100% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_deviceClusters.siddhiql rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql