From 0dc138dbb322c90e62c3912c83ea7615c4a5c604 Mon Sep 17 00:00:00 2001 From: inosh Date: Mon, 1 Jul 2024 10:51:52 +0530 Subject: [PATCH] add Geo fence crossing updates and fences on low power fixes https://roadmap.entgra.net/issues/11418 --- .../geo/service/GeoEventDeviceUpdate.java | 211 ++++++++++++++++++ .../service/GeoLocationProviderService.java | 15 ++ .../core/device/mgt/core/dao/GeofenceDAO.java | 15 ++ .../dao/impl/AbstractGeofenceDAOImpl.java | 64 ++++++ .../GeoLocationProviderServiceImpl.java | 39 +++- 5 files changed, 337 insertions(+), 7 deletions(-) create mode 100644 components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/geo/service/GeoEventDeviceUpdate.java diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/geo/service/GeoEventDeviceUpdate.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/geo/service/GeoEventDeviceUpdate.java new file mode 100644 index 0000000000..57caf02bde --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/geo/service/GeoEventDeviceUpdate.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.entgra.device.mgt.core.device.mgt.common.geo.service; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * Holds Device updates on events related to fence crossings + */ +@ApiModel(value = "GeoEventDeviceUpdate", description = "This class holds Device updates on events related to fence crossings") +public class GeoEventDeviceUpdate implements Serializable { + + private static final long serialVersionUID = 1448121761L; + + @ApiModelProperty(name = "id", value = "ID of the event in the database.") + private int id; + + @ApiModelProperty(name = "deviceId", value = "IDs of the reporting device") + private String deviceId; + + @ApiModelProperty(name = "eventType", value = "Type of fence crossing event.") + private String eventType; + + @ApiModelProperty(name = "fenceIds", value = "IDs of the event in the database.") + private int fenceId; + + @ApiModelProperty(name = "lat", value = "latitude of the current position") + private double lat; + + @ApiModelProperty(name = "lon", value = "longitude of the current position") + private double lon; + @ApiModelProperty(name = "street1", value = "street1 of the current position") + private String street1; + @ApiModelProperty(name = "street2", value = "street2 of the current position") + private String street2; + @ApiModelProperty(name = "city", value = "city of the current position") + private String city; + @ApiModelProperty(name = "zip", value = "zip of the current position") + private String zip; + @ApiModelProperty(name = "state", value = "state of the current position") + private String state; + @ApiModelProperty(name = "country", value = "country of the current position") + private String country; + @ApiModelProperty(name = "altitude", value = "altitude of the current position") + private double altitude; + @ApiModelProperty(name = "speed", value = "speed of the current position") + private float speed; + @ApiModelProperty(name = "bearing", value = "bearing of the current position") + private float bearing; + @ApiModelProperty(name = "distance", value = "distance of the current position") + private float distance; + @ApiModelProperty(name = "updatedTimestamp", value = "updatedTimestamp of the current position") + private long updatedTimestamp; + + public long getUpdatedTimestamp() { + return updatedTimestamp; + } + + public void setUpdatedTimestamp(long updatedTimestamp) { + this.updatedTimestamp = updatedTimestamp; + } + + public String getStreet1() { + return street1; + } + + public void setStreet1(String street1) { + this.street1 = street1; + } + + public String getStreet2() { + return street2; + } + + public void setStreet2(String street2) { + this.street2 = street2; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getZip() { + return zip; + } + + public void setZip(String zip) { + this.zip = zip; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public double getAltitude() { + return altitude; + } + + public void setAltitude(double altitude) { + this.altitude = altitude; + } + + public float getSpeed() { + return speed; + } + + public void setSpeed(float speed) { + this.speed = speed; + } + + public float getBearing() { + return bearing; + } + + public void setBearing(float bearing) { + this.bearing = bearing; + } + + public float getDistance() { + return distance; + } + + public void setDistance(float distance) { + this.distance = distance; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getEventType() { + return eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public int getFenceId() { + return fenceId; + } + + public void setFenceId(int fenceId) { + this.fenceId = fenceId; + } + + public double getLat() { + return lat; + } + + public void setLat(double lat) { + this.lat = lat; + } + + public double getLon() { + return lon; + } + + public void setLon(double lon) { + this.lon = lon; + } + +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/geo/service/GeoLocationProviderService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/geo/service/GeoLocationProviderService.java index c214971604..543551d7fd 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/geo/service/GeoLocationProviderService.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/geo/service/GeoLocationProviderService.java @@ -178,4 +178,19 @@ public interface GeoLocationProviderService { * @throws GeoLocationBasedServiceException any errors occurred while reading event records to geofence */ int getGeoFenceCount() throws GeoLocationBasedServiceException; + + /** + * Saves the geo-fence crossing event data for a device. + * + *

This method handles the transaction for saving the geo-fence crossing event data + * for a device, including retrieving the tenant ID and handling the necessary + * database operations. If any error occurs during the transaction, appropriate + * exceptions are thrown. + * + * @param geofenceData the geo-fence crossing event data to be saved. + * @return always returns {@code false}. + * @throws GeoLocationBasedServiceException if there is an error during the transaction + * or database operations. + */ + boolean saveGeoFenceCrossingDevice(GeoEventDeviceUpdate geofenceData) throws GeoLocationBasedServiceException; } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/GeofenceDAO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/GeofenceDAO.java index 1546d4034e..122f44edcb 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/GeofenceDAO.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/GeofenceDAO.java @@ -20,6 +20,7 @@ package io.entgra.device.mgt.core.device.mgt.core.dao; import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.event.config.EventConfig; +import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoEventDeviceUpdate; import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeofenceData; import io.entgra.device.mgt.core.device.mgt.core.dto.event.config.GeoFenceGroupMap; @@ -182,4 +183,18 @@ public interface GeofenceDAO { * @throws DeviceManagementDAOException */ int getGeofenceCount(int tenantId) throws DeviceManagementDAOException; + + /** + * Adds a geo-fence crossing event to the database for a specific device. + * + *

This method inserts the geo-fence crossing event data into the database. The data includes + * details about the device, event type, location coordinates, and additional contextual information. + * The method returns the generated ID of the newly inserted record. + * + * @param tenantId the tenant ID associated with the event. + * @param deviceEvent the geo-fence crossing event data to be added. + * @return the generated ID of the newly inserted record, or -1 if the insertion failed. + * @throws DeviceManagementDAOException if there is an error during the database operation. + */ + int addGeoFenceCrossingDevice(int tenantId, GeoEventDeviceUpdate deviceEvent) throws DeviceManagementDAOException; } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java index 9c560a35cc..0a8b47945a 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java @@ -18,6 +18,7 @@ package io.entgra.device.mgt.core.device.mgt.core.dao.impl; +import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoEventDeviceUpdate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import io.entgra.device.mgt.core.device.mgt.common.DeviceManagementConstants; @@ -28,6 +29,7 @@ import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOExceptio import io.entgra.device.mgt.core.device.mgt.core.dao.EventManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.dao.GeofenceDAO; import io.entgra.device.mgt.core.device.mgt.core.dto.event.config.GeoFenceGroupMap; +import org.wso2.carbon.context.CarbonContext; import java.sql.Connection; import java.sql.PreparedStatement; @@ -668,4 +670,66 @@ public abstract class AbstractGeofenceDAOImpl implements GeofenceDAO { } } + @Override + public int addGeoFenceCrossingDevice(int tenantId, GeoEventDeviceUpdate deviceEvent) throws DeviceManagementDAOException { + try { + CarbonContext context = CarbonContext.getThreadLocalCarbonContext(); + String username = context.getUsername(); + int genId = -1; + + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_GEOFECE_DEVICE_EVENT(" + + "DEVICE_ID, " + + "EVENT_TYPE, " + + "FENCE_ID, " + + "LATITUDE, " + + "LONGITUDE, " + + "UPDATE_TIMESTAMP, " + + "USERNAME, " + + "TENANT_ID," + + "STREET1, " + + "STREET2, " + + "CITY, " + + "ZIP, " + + "STATE, " + + "COUNTRY, " + + "ALTITUDE," + + "SPEED, " + + "BEARING," + + "DISTANCE) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, deviceEvent.getDeviceId()); + stmt.setString(2, deviceEvent.getEventType()); + stmt.setInt(3, deviceEvent.getFenceId()); + stmt.setDouble(4, deviceEvent.getLat()); + stmt.setDouble(5, deviceEvent.getLon()); + stmt.setTimestamp(6, new Timestamp(deviceEvent.getUpdatedTimestamp())); + stmt.setString(7, username); + stmt.setInt(8, tenantId); + stmt.setString(9, deviceEvent.getStreet1()); + stmt.setString(10, deviceEvent.getStreet2()); + stmt.setString(11, deviceEvent.getCity()); + stmt.setString(12, deviceEvent.getZip()); + stmt.setString(13, deviceEvent.getState()); + stmt.setString(14, deviceEvent.getCountry()); + stmt.setDouble(15, deviceEvent.getAltitude()); + stmt.setFloat(16, deviceEvent.getSpeed()); + stmt.setFloat(17, deviceEvent.getBearing()); + stmt.setFloat(18, deviceEvent.getDistance()); + if (stmt.executeUpdate() > 0) { + ResultSet generatedKeys = stmt.getGeneratedKeys(); + if (generatedKeys.next()) { + genId = generatedKeys.getInt(1); + } + } + return genId; + } + } catch (SQLException e) { + String msg = "Error occurred while creating Geofence event for the fence id " + deviceEvent.getFenceId() + " from device id: " + deviceEvent.getDeviceId(); + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java index edac4eaa09..0d8137454a 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java @@ -20,6 +20,7 @@ package io.entgra.device.mgt.core.device.mgt.core.geo.service; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import io.entgra.device.mgt.core.device.mgt.common.geo.service.*; import org.apache.axis2.AxisFault; import org.apache.axis2.client.Options; import org.apache.axis2.client.Stub; @@ -43,13 +44,6 @@ import io.entgra.device.mgt.core.device.mgt.common.event.config.EventConfig; import io.entgra.device.mgt.core.device.mgt.common.event.config.EventConfigurationException; import io.entgra.device.mgt.core.device.mgt.common.event.config.EventConfigurationProviderService; import io.entgra.device.mgt.core.device.mgt.common.exceptions.TransactionManagementException; -import io.entgra.device.mgt.core.device.mgt.common.geo.service.Alert; -import io.entgra.device.mgt.core.device.mgt.common.geo.service.AlertAlreadyExistException; -import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoFence; -import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoFenceEventMeta; -import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoLocationBasedServiceException; -import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoLocationProviderService; -import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeofenceData; import io.entgra.device.mgt.core.device.mgt.core.cache.impl.GeoCacheManagerImpl; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; @@ -1773,6 +1767,37 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public boolean saveGeoFenceCrossingDevice(GeoEventDeviceUpdate geofenceData) throws GeoLocationBasedServiceException { + int tenantId; + try { + tenantId = DeviceManagementDAOUtil.getTenantId(); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving tenant id while get geofence data"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } + + try { + EventManagementDAOFactory.beginTransaction(); + geofenceDAO.addGeoFenceCrossingDevice(tenantId, geofenceData); + EventManagementDAOFactory.commitTransaction(); + } catch (TransactionManagementException e) { + String msg = "Failed to begin transaction for saving geofence"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } catch (DeviceManagementDAOException e) { + EventManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while saving geofence"; + log.error(msg, e); + throw new GeoLocationBasedServiceException(msg, e); + } finally { + EventManagementDAOFactory.closeConnection(); + } + + return false; + } + /** * Delete events of geofence *