diff --git a/backend/pom.xml b/backend/pom.xml index 50d5f52..782477a 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -1,98 +1,104 @@ - - 4.0.0 - net.miarma - contaminus - 1.0.0 - ContaminUS - - - 23 - 23 - - - - - - io.vertx - vertx-core - 4.5.13 - - - - - io.vertx - vertx-web - 4.5.13 - - - - - io.vertx - vertx-web-client - 4.5.13 - - - - - io.vertx - vertx-mqtt - 4.4.2 - - - - - io.vertx - vertx-jdbc-client - 4.5.13 - - - - - org.mariadb.jdbc - mariadb-java-client - 3.5.2 - - - - - com.google.code.gson - gson - 2.12.1 - - - - - org.jboss.logmanager - jboss-logmanager - 3.1.1.Final - - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.3 - - - package - - shade - - - false - - - net.miarma.contaminus.server.MainVerticle - - - - - - - - + + 4.0.0 + net.miarma + contaminus + 1.0.0 + ContaminUS + + + 23 + 23 + + + + + + io.vertx + vertx-core + 4.5.13 + + + + + io.vertx + vertx-mysql-client + 4.5.13 + + + + + io.vertx + vertx-web + 4.5.13 + + + + + io.vertx + vertx-web-client + 4.5.13 + + + + + io.vertx + vertx-mqtt + 4.4.2 + + + + + io.vertx + vertx-jdbc-client + 4.5.13 + + + + + com.google.code.gson + gson + 2.12.1 + + + + + org.slf4j + slf4j-api + 2.0.12 + + + + ch.qos.logback + logback-classic + 1.5.13 + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.3 + + + package + + shade + + + false + + + net.miarma.contaminus.server.MainVerticle + + + + + + + + \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/common/AbstractEntity.java b/backend/src/main/java/net/miarma/contaminus/common/AbstractEntity.java new file mode 100644 index 0000000..87db4d7 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/common/AbstractEntity.java @@ -0,0 +1,113 @@ +package net.miarma.contaminus.common; + +import java.lang.reflect.Field; + +import io.vertx.core.json.JsonObject; +import io.vertx.sqlclient.Row; + +public abstract class AbstractEntity { + + public AbstractEntity() {} + + public AbstractEntity(Row row) { + populateFromRow(row); + } + + private void populateFromRow(Row row) { + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + try { + field.setAccessible(true); + Class type = field.getType(); + String name = field.getName(); + + Object value; + if (type.isEnum()) { + Integer intValue = row.getInteger(name); + if (intValue != null) { + try { + var method = type.getMethod("fromInt", int.class); + value = method.invoke(null, intValue); + } catch (Exception e) { + value = null; + } + } else { + value = null; + } + } else { + value = switch (type.getSimpleName()) { + case "Integer" -> row.getInteger(name); + case "String" -> row.getString(name); + case "Double" -> row.getDouble(name); + case "Long" -> row.getLong(name); + case "Boolean" -> row.getBoolean(name); + case "int" -> row.getInteger(name); + case "double" -> row.getDouble(name); + case "long" -> row.getLong(name); + case "boolean" -> row.getBoolean(name); + case "LocalDateTime" -> row.getLocalDateTime(name); + case "BigDecimal" -> { + try { + var numeric = row.get(io.vertx.sqlclient.data.Numeric.class, row.getColumnIndex(name)); + yield numeric != null ? numeric.bigDecimalValue() : null; + } catch (Exception e) { + yield null; + } + } + default -> { + System.err.println("Type not supported yet: " + type.getName() + " for field " + name); + yield null; + } + }; + + } + + field.set(this, value); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public String encode() { + JsonObject json = new JsonObject(); + Class clazz = this.getClass(); + + while (clazz != null) { + for (Field field : clazz.getDeclaredFields()) { + field.setAccessible(true); + try { + Object value = field.get(this); + + if (value instanceof ValuableEnum ve) { + json.put(field.getName(), ve.getValue()); + } else { + json.put(field.getName(), value); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + clazz = clazz.getSuperclass(); + } + + return json.encode(); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(this.getClass().getSimpleName()).append(" [ "); + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + try { + sb.append(field.getName()).append("= ").append(field.get(this)).append(", "); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + sb.append("]"); + return sb.toString(); + } + +} diff --git a/backend/src/main/java/net/miarma/contaminus/common/Constants.java b/backend/src/main/java/net/miarma/contaminus/common/Constants.java index 6e08942..6b85463 100644 --- a/backend/src/main/java/net/miarma/contaminus/common/Constants.java +++ b/backend/src/main/java/net/miarma/contaminus/common/Constants.java @@ -1,57 +1,42 @@ -package net.miarma.contaminus.common; - -import io.vertx.core.impl.logging.Logger; -import io.vertx.core.impl.logging.LoggerFactory; - -public class Constants { - public static final String APP_NAME = "ContaminUS"; - public static final String API_PREFIX = "/api/v1"; - public static final String RAW_API_PREFIX = "/api/raw/v1"; - public static Logger LOGGER = LoggerFactory.getLogger(Constants.APP_NAME); - - - /* API Endpoints */ - public static final String POST_PAYLOAD = RAW_API_PREFIX + "/device-payload"; - - public static final String GET_GROUPS = RAW_API_PREFIX + "/groups"; - public static final String POST_GROUPS = RAW_API_PREFIX + "/groups"; - public static final String PUT_GROUP_BY_ID = RAW_API_PREFIX + "/groups/:groupId"; - - public static final String GET_DEVICES = RAW_API_PREFIX + "/devices"; - public static final String POST_DEVICES = RAW_API_PREFIX + "/devices"; - public static final String PUT_DEVICE_BY_ID = RAW_API_PREFIX + "/devices/:deviceId"; - - public static final String GET_SENSORS = RAW_API_PREFIX + "/sensors"; - public static final String POST_SENSORS = RAW_API_PREFIX + "/sensors"; - public static final String PUT_SENSOR_BY_ID = RAW_API_PREFIX + "/sensors/:sensorId"; - - public static final String GET_ACTUATORS = RAW_API_PREFIX + "/actuators"; - public static final String POST_ACTUATORS = RAW_API_PREFIX + "/actuators"; - public static final String PUT_ACTUATOR_BY_ID = RAW_API_PREFIX + "/actuators/:actuatorId"; - - public static final String GET_CO_BY_DEVICE_VIEW = RAW_API_PREFIX + "/v_co_by_device"; - - public static final String GET_GPS_BY_DEVICE_VIEW = RAW_API_PREFIX + "/v_gps_by_device"; - public static final String GET_LATEST_VALUES_VIEW = RAW_API_PREFIX + "/v_latest_values"; - public static final String GET_POLLUTION_MAP_VIEW = RAW_API_PREFIX + "/v_pollution_map"; - public static final String GET_SENSOR_HISTORY_BY_DEVICE_VIEW = RAW_API_PREFIX + "/v_sensor_history_by_device"; - public static final String GET_SENSOR_VALUES_VIEW = RAW_API_PREFIX + "/v_sensor_values"; - public static final String GET_WEATHER_BY_DEVICE_VIEW = RAW_API_PREFIX + "/v_weather_by_device"; - - /* Bussiness Logic API */ - public static final String GET_GROUP_BY_ID = API_PREFIX + "/groups/:groupId"; - public static final String GET_GROUP_DEVICES = API_PREFIX + "/groups/:groupId/devices"; - public static final String GET_DEVICE_BY_ID = API_PREFIX + "/devices/:deviceId"; - public static final String GET_DEVICE_SENSORS = API_PREFIX + "/devices/:deviceId/sensors"; - public static final String GET_DEVICE_ACTUATORS = API_PREFIX + "/devices/:deviceId/actuators"; - public static final String GET_DEVICE_LATEST_VALUES = API_PREFIX + "/devices/:deviceId/latest"; - public static final String GET_DEVICE_POLLUTION_MAP = API_PREFIX + "/devices/:deviceId/pollution-map"; - public static final String GET_DEVICE_HISTORY = API_PREFIX + "/devices/:deviceId/history"; - public static final String GET_SENSOR_BY_ID = API_PREFIX + "/sensors/:sensorId"; - public static final String GET_SENSOR_VALUES = API_PREFIX + "/sensors/:sensorId/values"; - public static final String GET_ACTUATOR_BY_ID = API_PREFIX + "/actuators/:actuatorId"; - - private Constants() { - throw new AssertionError("Utility class cannot be instantiated."); - } -} +package net.miarma.contaminus.common; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Constants { + public static final String APP_NAME = "ContaminUS"; + public static final String API_PREFIX = "/api/v1"; + public static final String RAW_API_PREFIX = "/api/raw/v1"; + public static final String CONTAMINUS_EB = "contaminus.eventbus"; + public static Logger LOGGER = LoggerFactory.getLogger(Constants.APP_NAME); + + /* API Endpoints */ + public static final String GROUPS = RAW_API_PREFIX + "/groups"; + public static final String GROUP = RAW_API_PREFIX + "/groups/:groupId"; + + public static final String DEVICES = RAW_API_PREFIX + "/groups/:groupId/devices"; + public static final String DEVICE = RAW_API_PREFIX + "/groups/:groupId/devices/:deviceId"; + public static final String LATEST_VALUES = API_PREFIX + "/groups/:groupId/devices/:deviceId/latest-values"; + public static final String POLLUTION_MAP = API_PREFIX + "/groups/:groupId/devices/:deviceId/pollution-map"; + public static final String HISTORY = API_PREFIX + "/groups/:groupId/devices/:deviceId/history"; + + public static final String SENSORS = RAW_API_PREFIX + "/groups/:groupId/devices/:deviceId/sensors"; + public static final String SENSOR = RAW_API_PREFIX + "/groups/:groupId/devices/:deviceId/sensors/:sensorId"; + public static final String SENSOR_VALUES = API_PREFIX + "/groups/:groupId/devices/:deviceId/sensors/:sensorId/values"; + + public static final String ACTUATORS = RAW_API_PREFIX + "/groups/:groupId/devices/:deviceId/actuators"; + public static final String ACTUATOR = RAW_API_PREFIX + "/groups/:groupId/devices/:deviceId/actuators/:actuator_id"; + public static final String ACTUATOR_STATUS = API_PREFIX + "/groups/:groupId/devices/:deviceId/actuators/:actuator_id/status"; + + public static final String VIEW_LATEST_VALUES = RAW_API_PREFIX + "/v_latest_values"; + public static final String VIEW_POLLUTION_MAP = RAW_API_PREFIX + "/v_pollution_map"; + public static final String VIEW_SENSOR_HISTORY = RAW_API_PREFIX + "/v_sensor_history_by_device"; + public static final String VIEW_SENSOR_VALUES = RAW_API_PREFIX + "/v_sensor_values"; + public static final String VIEW_CO_BY_DEVICE = RAW_API_PREFIX + "/v_co_by_device"; + public static final String VIEW_GPS_BY_DEVICE = RAW_API_PREFIX + "/v_gps_by_device"; + public static final String VIEW_WEATHER_BY_DEVICE = RAW_API_PREFIX + "/v_weather_by_device"; + + private Constants() { + throw new AssertionError("Utility class cannot be instantiated."); + } +} diff --git a/backend/src/main/java/net/miarma/contaminus/common/ValuableEnum.java b/backend/src/main/java/net/miarma/contaminus/common/ValuableEnum.java new file mode 100644 index 0000000..73f6c92 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/common/ValuableEnum.java @@ -0,0 +1,5 @@ +package net.miarma.contaminus.common; + +public interface ValuableEnum { + int getValue(); +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/ActuatorDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/ActuatorDAO.java new file mode 100644 index 0000000..c6a3336 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/ActuatorDAO.java @@ -0,0 +1,129 @@ +package net.miarma.contaminus.dao; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.Actuator; + +public class ActuatorDAO implements DataAccessObject{ + + private final DatabaseManager db; + + public ActuatorDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(Actuator.class).build(); + db.execute(query, Actuator.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + public Future> getAllByDeviceId(String deviceId) { + Promise> promise = Promise.promise(); + Actuator actuator = new Actuator(); + actuator.setDeviceId(deviceId); + + String query = QueryBuilder + .select(Actuator.class) + .where(actuator) + .build(); + + db.execute(query, Actuator.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future getById(Integer id) { + Promise promise = Promise.promise(); + Actuator actuator = new Actuator(); + actuator.setActuatorId(id); + + String query = QueryBuilder + .select(Actuator.class) + .where(actuator) + .build(); + + db.execute(query, Actuator.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + public Future getByIdAndDeviceId(Integer actuatorId, String deviceId) { + Promise promise = Promise.promise(); + Actuator actuator = new Actuator(); + actuator.setDeviceId(deviceId); + actuator.setActuatorId(actuatorId); + + String query = QueryBuilder + .select(Actuator.class) + .where(actuator) + .build(); + + db.execute(query, Actuator.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(Actuator t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.insert(t).build(); + + db.execute(query, Actuator.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future update(Actuator t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.update(t).build(); + + db.execute(query, Actuator.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future delete(Integer id) { + Promise promise = Promise.promise(); + Actuator actuator = new Actuator(); + actuator.setActuatorId(id); + + String query = QueryBuilder.delete(actuator).build(); + + db.executeOne(query, Actuator.class, + _ -> promise.complete(actuator), + promise::fail + ); + + return promise.future(); + } +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/COValueDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/COValueDAO.java new file mode 100644 index 0000000..e7655c0 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/COValueDAO.java @@ -0,0 +1,82 @@ +package net.miarma.contaminus.dao; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.COValue; + +public class COValueDAO implements DataAccessObject { + + private final DatabaseManager db; + + public COValueDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(COValue.class).build(); + db.execute(query, COValue.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + @Override + public Future getById(Integer id) { + Promise promise = Promise.promise(); + COValue coValue = new COValue(); + coValue.setValueId(id); + + String query = QueryBuilder + .select(COValue.class) + .where(coValue) + .build(); + + db.execute(query, COValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(COValue t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.insert(t).build(); + + db.execute(query, COValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future update(COValue t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.update(t).build(); + + db.execute(query, COValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future delete(Integer id) { + throw new UnsupportedOperationException("Cannot delete samples"); + } + +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/DeviceDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/DeviceDAO.java new file mode 100644 index 0000000..5ef87e9 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/DeviceDAO.java @@ -0,0 +1,128 @@ +package net.miarma.contaminus.dao; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.Device; + +public class DeviceDAO implements DataAccessObject { + + private final DatabaseManager db; + + public DeviceDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(Device.class).build(); + db.execute(query, Device.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + public Future> getAllByGroupId(Integer groupId) { + Promise> promise = Promise.promise(); + Device device = new Device(); + device.setGroupId(groupId); + + String query = QueryBuilder + .select(Device.class) + .where(device) + .build(); + + db.execute(query, Device.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future getById(String id) { + Promise promise = Promise.promise(); + Device device = new Device(); + device.setDeviceId(id); + + String query = QueryBuilder + .select(Device.class) + .where(device) + .build(); + + db.execute(query, Device.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + public Future getByIdAndGroupId(String id, Integer groupId) { + Promise promise = Promise.promise(); + Device device = new Device(); + device.setDeviceId(id); + device.setGroupId(groupId); + + String query = QueryBuilder + .select(Device.class) + .where(device) + .build(); + + db.execute(query, Device.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(Device t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.insert(t).build(); + + db.execute(query, Device.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future update(Device t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.update(t).build(); + + db.execute(query, Device.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future delete(String id) { + Promise promise = Promise.promise(); + Device device = new Device(); + device.setDeviceId(id); + String query = QueryBuilder.delete(device).build(); + + db.execute(query, Device.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/GpsValueDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/GpsValueDAO.java new file mode 100644 index 0000000..3982493 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/GpsValueDAO.java @@ -0,0 +1,81 @@ +package net.miarma.contaminus.dao; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.GpsValue; + +public class GpsValueDAO implements DataAccessObject { + + private final DatabaseManager db; + + public GpsValueDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(GpsValue.class).build(); + db.execute(query, GpsValue.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + @Override + public Future getById(Integer id) { + Promise promise = Promise.promise(); + GpsValue gpsValue = new GpsValue(); + gpsValue.setValueId(id); + + String query = QueryBuilder + .select(GpsValue.class) + .where(gpsValue) + .build(); + + db.execute(query, GpsValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(GpsValue t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.insert(t).build(); + + db.execute(query, GpsValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future update(GpsValue t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.update(t).build(); + + db.execute(query, GpsValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future delete(Integer id) { + throw new UnsupportedOperationException("Cannot delete samples"); + } +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/GroupDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/GroupDAO.java new file mode 100644 index 0000000..ea3e377 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/GroupDAO.java @@ -0,0 +1,93 @@ +package net.miarma.contaminus.dao; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.Group; + +public class GroupDAO implements DataAccessObject { + +private final DatabaseManager db; + + public GroupDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(Group.class).build(); + db.execute(query, Group.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + @Override + public Future getById(Integer id) { + Promise promise = Promise.promise(); + Group group = new Group(); + group.setGroupId(id); + + String query = QueryBuilder + .select(Group.class) + .where(group) + .build(); + + db.execute(query, Group.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(Group t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.insert(t).build(); + + db.execute(query, Group.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future update(Group t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.update(t).build(); + + db.execute(query, Group.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future delete(Integer id) { + Promise promise = Promise.promise(); + Group group = new Group(); + group.setGroupId(id); + + String query = QueryBuilder.delete(group).build(); + + db.execute(query, Group.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/SensorDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/SensorDAO.java new file mode 100644 index 0000000..c3e0328 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/SensorDAO.java @@ -0,0 +1,130 @@ +package net.miarma.contaminus.dao; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.Sensor; + +public class SensorDAO implements DataAccessObject { + + private final DatabaseManager db; + + public SensorDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(Sensor.class).build(); + db.execute(query, Sensor.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + public Future> getAllByDeviceId(String deviceId) { + Promise> promise = Promise.promise(); + Sensor sensor = new Sensor(); + sensor.setDeviceId(deviceId); + + String query = QueryBuilder + .select(Sensor.class) + .where(sensor) + .build(); + + db.execute(query, Sensor.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future getById(Integer id) { + Promise promise = Promise.promise(); + Sensor sensor = new Sensor(); + sensor.setSensorId(id); + + String query = QueryBuilder + .select(Sensor.class) + .where(sensor) + .build(); + + db.execute(query, Sensor.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + public Future getByIdAndDeviceId(Integer sensorId, String deviceId) { + Promise promise = Promise.promise(); + Sensor sensor = new Sensor(); + sensor.setDeviceId(deviceId); + sensor.setSensorId(sensorId); + + String query = QueryBuilder + .select(Sensor.class) + .where(sensor) + .build(); + + db.execute(query, Sensor.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(Sensor t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.insert(t).build(); + + db.execute(query, Sensor.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future update(Sensor t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.update(t).build(); + + db.execute(query, Sensor.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future delete(Integer id) { + Promise promise = Promise.promise(); + Sensor sensor = new Sensor(); + + sensor.setSensorId(id); + + String query = QueryBuilder.delete(sensor).build(); + + db.execute(query, Sensor.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/WeatherValueDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/WeatherValueDAO.java new file mode 100644 index 0000000..d9d4e28 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/WeatherValueDAO.java @@ -0,0 +1,81 @@ +package net.miarma.contaminus.dao; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.WeatherValue; + +public class WeatherValueDAO implements DataAccessObject { + + private final DatabaseManager db; + + public WeatherValueDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(WeatherValue.class).build(); + db.execute(query, WeatherValue.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + @Override + public Future getById(Integer id) { + Promise promise = Promise.promise(); + WeatherValue weatherValue = new WeatherValue(); + weatherValue.setValueId(id); + + String query = QueryBuilder + .select(WeatherValue.class) + .where(weatherValue) + .build(); + + db.execute(query, WeatherValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(WeatherValue t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.insert(t).build(); + + db.execute(query, WeatherValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future update(WeatherValue t) { + Promise promise = Promise.promise(); + String query = QueryBuilder.update(t).build(); + + db.execute(query, WeatherValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future delete(Integer id) { + throw new UnsupportedOperationException("Cannot delete samples"); + } +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/views/ViewLatestValuesDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/views/ViewLatestValuesDAO.java new file mode 100644 index 0000000..6679367 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/views/ViewLatestValuesDAO.java @@ -0,0 +1,66 @@ +package net.miarma.contaminus.dao.views; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.ViewLatestValues; + +public class ViewLatestValuesDAO implements DataAccessObject { + + private final DatabaseManager db; + + public ViewLatestValuesDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(ViewLatestValues.class).build(); + db.execute(query, ViewLatestValues.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + @Override + public Future getById(String id) { + Promise promise = Promise.promise(); + ViewLatestValues view = new ViewLatestValues(); + view.setDeviceId(id); + + String query = QueryBuilder + .select(ViewLatestValues.class) + .where(view) + .build(); + + db.execute(query, ViewLatestValues.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(ViewLatestValues t) { + throw new UnsupportedOperationException("Insert not supported for views"); + } + + @Override + public Future update(ViewLatestValues t) { + throw new UnsupportedOperationException("Update not supported for views"); + } + + @Override + public Future delete(String id) { + throw new UnsupportedOperationException("Delete not supported for views"); + } + +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/views/ViewPollutionMapDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/views/ViewPollutionMapDAO.java new file mode 100644 index 0000000..0ec7e2c --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/views/ViewPollutionMapDAO.java @@ -0,0 +1,66 @@ +package net.miarma.contaminus.dao.views; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.ViewPollutionMap; + +@Table("v_pollution_map") +public class ViewPollutionMapDAO implements DataAccessObject { + + private final DatabaseManager db; + public ViewPollutionMapDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(ViewPollutionMap.class).build(); + db.execute(query, ViewPollutionMap.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + @Override + public Future getById(String id) { + Promise promise = Promise.promise(); + ViewPollutionMap view = new ViewPollutionMap(); + view.setDeviceId(id); + + String query = QueryBuilder + .select(ViewPollutionMap.class) + .where(view) + .build(); + + db.execute(query, ViewPollutionMap.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(ViewPollutionMap t) { + throw new UnsupportedOperationException("Insert not supported for views"); + } + + @Override + public Future update(ViewPollutionMap t) { + throw new UnsupportedOperationException("Update not supported for views"); + } + + @Override + public Future delete(String id) { + throw new UnsupportedOperationException("Delete not supported for views"); + } +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/views/ViewSensorHistoryDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/views/ViewSensorHistoryDAO.java new file mode 100644 index 0000000..d9d5f79 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/views/ViewSensorHistoryDAO.java @@ -0,0 +1,67 @@ +package net.miarma.contaminus.dao.views; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.ViewSensorHistory; + +public class ViewSensorHistoryDAO implements DataAccessObject { + + private final DatabaseManager db; + + public ViewSensorHistoryDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(ViewSensorHistory.class).build(); + db.execute(query, ViewSensorHistory.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + @Override + public Future getById(String id) { + Promise promise = Promise.promise(); + ViewSensorHistory viewSensorHistory = new ViewSensorHistory(); + viewSensorHistory.setDeviceId(id); + + String query = QueryBuilder + .select(ViewSensorHistory.class) + .where(viewSensorHistory) + .build(); + + db.execute(query, ViewSensorHistory.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(ViewSensorHistory t) { + throw new UnsupportedOperationException("Insert not supported for views"); + } + + @Override + public Future update(ViewSensorHistory t) { + throw new UnsupportedOperationException("Update not supported for views"); + } + + @Override + public Future delete(String id) { + throw new UnsupportedOperationException("Delete not supported for views"); + } + + +} diff --git a/backend/src/main/java/net/miarma/contaminus/dao/views/ViewSensorValueDAO.java b/backend/src/main/java/net/miarma/contaminus/dao/views/ViewSensorValueDAO.java new file mode 100644 index 0000000..5d58ff6 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/dao/views/ViewSensorValueDAO.java @@ -0,0 +1,66 @@ +package net.miarma.contaminus.dao.views; + +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.db.DataAccessObject; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.ViewSensorValue; + +public class ViewSensorValueDAO implements DataAccessObject { + + private final DatabaseManager db; + + public ViewSensorValueDAO(Pool pool) { + this.db = DatabaseManager.getInstance(pool); + } + + @Override + public Future> getAll() { + Promise> promise = Promise.promise(); + String query = QueryBuilder.select(ViewSensorValue.class).build(); + db.execute(query, ViewSensorValue.class, + list -> promise.complete(list.isEmpty() ? List.of() : list), + promise::fail + ); + return promise.future(); + } + + @Override + public Future getById(Integer id) { + Promise promise = Promise.promise(); + ViewSensorValue view = new ViewSensorValue(); + view.setSensorId(id); + + String query = QueryBuilder + .select(ViewSensorValue.class) + .where(view) + .build(); + + db.execute(query, ViewSensorValue.class, + list -> promise.complete(list.isEmpty() ? null : list.get(0)), + promise::fail + ); + + return promise.future(); + } + + @Override + public Future insert(ViewSensorValue t) { + throw new UnsupportedOperationException("Insert not supported for views"); + } + + @Override + public Future update(ViewSensorValue t) { + throw new UnsupportedOperationException("Update not supported for views"); + } + + @Override + public Future delete(Integer id) { + throw new UnsupportedOperationException("Delete not supported for views"); + } + +} diff --git a/backend/src/main/java/net/miarma/contaminus/database/DatabaseManager.java b/backend/src/main/java/net/miarma/contaminus/database/DatabaseManager.java deleted file mode 100644 index 9c1d350..0000000 --- a/backend/src/main/java/net/miarma/contaminus/database/DatabaseManager.java +++ /dev/null @@ -1,58 +0,0 @@ -package net.miarma.contaminus.database; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; - -import io.vertx.core.Future; -import io.vertx.core.Handler; -import io.vertx.jdbcclient.JDBCPool; -import io.vertx.sqlclient.Row; -import io.vertx.sqlclient.RowSet; -import net.miarma.contaminus.common.Constants; - -public class DatabaseManager { - private static DatabaseManager instance; - private final JDBCPool pool; - - private DatabaseManager(JDBCPool pool) { - this.pool = pool; - } - - public static synchronized DatabaseManager getInstance(JDBCPool pool) { - if (instance == null) { - instance = new DatabaseManager(pool); - } - return instance; - } - - public Future> testConnection() { - return pool.query("SELECT 1").execute(); - } - - public Future> execute(String query, Class clazz, - Handler> onSuccess, Handler onFailure) { - return pool.query(query).execute() - .map(rows -> { - List results = new ArrayList<>(); - for (Row row : rows) { - try { - Constructor constructor = clazz.getConstructor(Row.class); - results.add(constructor.newInstance(row)); - } catch (NoSuchMethodException | InstantiationException | - IllegalAccessException | InvocationTargetException e) { - Constants.LOGGER.error("Error instantiating class: " + e.getMessage()); - } - } - return results; - }) - .onComplete(ar -> { - if (ar.succeeded()) { - onSuccess.handle(ar.result()); - } else { - onFailure.handle(ar.cause()); - } - }); - } -} diff --git a/backend/src/main/java/net/miarma/contaminus/database/QueryBuilder.java b/backend/src/main/java/net/miarma/contaminus/database/QueryBuilder.java deleted file mode 100644 index ebfc658..0000000 --- a/backend/src/main/java/net/miarma/contaminus/database/QueryBuilder.java +++ /dev/null @@ -1,196 +0,0 @@ -package net.miarma.contaminus.database; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.StringJoiner; - -import net.miarma.contaminus.common.Constants; -import net.miarma.contaminus.common.Table; - -public class QueryBuilder { - private StringBuilder query; - private String sort; - private String order; - private String limit; - - public QueryBuilder() { - this.query = new StringBuilder(); - } - - private static String getTableName(Class clazz) { - if (clazz == null) { - throw new IllegalArgumentException("Class cannot be null"); - } - - if (clazz.isAnnotationPresent(Table.class)) { - Table annotation = clazz.getAnnotation(Table.class); - return annotation.value(); - } - throw new IllegalArgumentException("Class does not have @Table annotation"); - } - - public String getQuery() { - return query.toString(); - } - - public static QueryBuilder select(Class clazz, String... columns) { - if (clazz == null) { - throw new IllegalArgumentException("Class cannot be null"); - } - - QueryBuilder qb = new QueryBuilder(); - String tableName = getTableName(clazz); - - qb.query.append("SELECT "); - - if (columns.length == 0) { - qb.query.append("* "); - } else { - StringJoiner joiner = new StringJoiner(", "); - for (String column : columns) { - if (column != null) { - joiner.add(column); - } - } - qb.query.append(joiner).append(" "); - } - - qb.query.append("FROM ").append(tableName).append(" "); - return qb; - } - - public static QueryBuilder where(QueryBuilder qb, T object) { - if (qb == null || object == null) { - throw new IllegalArgumentException("QueryBuilder and object cannot be null"); - } - - List conditions = new ArrayList<>(); - Class clazz = object.getClass(); - - for (Field field : clazz.getDeclaredFields()) { - field.setAccessible(true); - try { - Object value = field.get(object); - if (value != null) { - if (value instanceof String) { - conditions.add(field.getName() + " = '" + value + "'"); - } else { - conditions.add(field.getName() + " = " + value); - } - } - } catch (IllegalAccessException e) { - Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); - } - } - - if (!conditions.isEmpty()) { - qb.query.append("WHERE ").append(String.join(" AND ", conditions)).append(" "); - } - - return qb; - } - - public static QueryBuilder select(T object, String... columns) { - if (object == null) { - throw new IllegalArgumentException("Object cannot be null"); - } - Class clazz = object.getClass(); - QueryBuilder qb = select(clazz, columns); - return where(qb, object); - } - - public static QueryBuilder insert(T object) { - if (object == null) { - throw new IllegalArgumentException("Object cannot be null"); - } - - QueryBuilder qb = new QueryBuilder(); - String table = getTableName(object.getClass()); - qb.query.append("INSERT INTO ").append(table).append(" "); - qb.query.append("("); - StringJoiner columns = new StringJoiner(", "); - StringJoiner values = new StringJoiner(", "); - for (Field field : object.getClass().getDeclaredFields()) { - field.setAccessible(true); - try { - columns.add(field.getName()); - Object fieldValue = field.get(object); - if (fieldValue != null) { - if (fieldValue instanceof String) { - values.add("'" + fieldValue + "'"); - } else { - values.add(fieldValue.toString()); - } - } else { - values.add("NULL"); - } - } catch (IllegalArgumentException | IllegalAccessException e) { - Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); - } - } - qb.query.append(columns).append(") "); - qb.query.append("VALUES (").append(values).append(") "); - return qb; - } - - public static QueryBuilder update(T object) { - if (object == null) { - throw new IllegalArgumentException("Object cannot be null"); - } - - QueryBuilder qb = new QueryBuilder(); - String table = getTableName(object.getClass()); - qb.query.append("UPDATE ").append(table).append(" "); - qb.query.append("SET "); - StringJoiner joiner = new StringJoiner(", "); - for (Field field : object.getClass().getDeclaredFields()) { - field.setAccessible(true); - try { - Object fieldValue = field.get(object); - if (fieldValue != null) { - if (fieldValue instanceof String) { - joiner.add(field.getName() + " = '" + fieldValue + "'"); - } else { - joiner.add(field.getName() + " = " + fieldValue.toString()); - } - } else { - joiner.add(field.getName() + " = NULL"); - } - } catch (IllegalArgumentException | IllegalAccessException e) { - Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); - } - } - qb.query.append(joiner).append(" "); - return qb; - } - - public QueryBuilder orderBy(Optional column, Optional order) { - column.ifPresent(c -> { - sort = "ORDER BY " + c + " "; - order.ifPresent(o -> { - sort += o.equalsIgnoreCase("asc") ? "ASC" : "DESC" + " "; - }); - }); - return this; - } - - public QueryBuilder limit(Optional limitParam) { - limitParam.ifPresent(param -> limit = "LIMIT " + param + " "); - return this; - } - - public String build() { - if (order != null && !order.isEmpty()) { - query.append(order); - } - if (sort != null && !sort.isEmpty()) { - query.append(sort); - } - if (limit != null && !limit.isEmpty()) { - query.append(limit); - } - return query.toString().trim() + ";"; - } -} diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceCO.java b/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceCO.java deleted file mode 100644 index 4e632d8..0000000 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceCO.java +++ /dev/null @@ -1,67 +0,0 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("v_co_by_device") -public class DeviceCO { - private String deviceId; - private Float carbonMonoxide; - private Long timestamp; - - public DeviceCO() {} - - public DeviceCO(Row row) { - this.deviceId = row.getString("deviceId"); - this.carbonMonoxide = row.getFloat("carbonMonoxide"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public DeviceCO(String deviceId, Float carbonMonoxide, Long timestamp) { - super(); - this.deviceId = deviceId; - this.carbonMonoxide = carbonMonoxide; - this.timestamp = timestamp; - } - - public String getDeviceId() { - return deviceId; - } - - public Float getCarbonMonoxide() { - return carbonMonoxide; - } - - public Long getTimestamp() { - return timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(carbonMonoxide, deviceId, timestamp); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DeviceCO other = (DeviceCO) obj; - return Objects.equals(carbonMonoxide, other.carbonMonoxide) && Objects.equals(deviceId, other.deviceId) - && Objects.equals(timestamp, other.timestamp); - } - - @Override - public String toString() { - return "DeviceCO [deviceId=" + deviceId + ", carbonMonoxide=" + carbonMonoxide + ", timestamp=" + timestamp - + "]"; - } - - -} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceGPS.java b/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceGPS.java deleted file mode 100644 index ae70f79..0000000 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceGPS.java +++ /dev/null @@ -1,72 +0,0 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("v_gps_by_device") -public class DeviceGPS { - private String deviceId; - private Float lat; - private Float lon; - private Long timestamp; - - public DeviceGPS() {} - - public DeviceGPS(Row row) { - this.deviceId = row.getString("deviceId"); - this.lat = row.getFloat("lat"); - this.lon = row.getFloat("lon"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public DeviceGPS(String deviceId, Float lat, Float lon) { - super(); - this.deviceId = deviceId; - this.lat = lat; - this.lon = lon; - } - - public String getDeviceId() { - return deviceId; - } - - public Float getLat() { - return lat; - } - - public Float getLon() { - return lon; - } - - public Long getTimestamp() { - return timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(deviceId, lat, lon, timestamp); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DeviceGPS other = (DeviceGPS) obj; - return Objects.equals(deviceId, other.deviceId) && Objects.equals(lat, other.lat) - && Objects.equals(lon, other.lon) && Objects.equals(timestamp, other.timestamp); - } - - @Override - public String toString() { - return "DeviceGPS [deviceId=" + deviceId + ", lat=" + lat + ", lon=" + lon + ", timestamp=" + timestamp + "]"; - } - - -} diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceWeather.java b/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceWeather.java deleted file mode 100644 index f156444..0000000 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceWeather.java +++ /dev/null @@ -1,74 +0,0 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("v_weather_by_device") -public class DeviceWeather { - private String deviceId; - private Float temperature; - private Float humidity; - private Long timestamp; - - public DeviceWeather() {} - - public DeviceWeather(Row row) { - this.deviceId = row.getString("deviceId"); - this.temperature = row.getFloat("temperature"); - this.humidity = row.getFloat("humidity"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public DeviceWeather(String deviceId, Float temperature, Float humidity, Long timestamp) { - super(); - this.deviceId = deviceId; - this.temperature = temperature; - this.humidity = humidity; - this.timestamp = timestamp; - } - - public String getDeviceId() { - return deviceId; - } - - public Float getTemperature() { - return temperature; - } - - public Float getHumidity() { - return humidity; - } - - public Long getTimestamp() { - return timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(deviceId, humidity, temperature, timestamp); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DeviceWeather other = (DeviceWeather) obj; - return Objects.equals(deviceId, other.deviceId) && Objects.equals(humidity, other.humidity) - && Objects.equals(temperature, other.temperature) && Objects.equals(timestamp, other.timestamp); - } - - @Override - public String toString() { - return "DeviceWeather [deviceId=" + deviceId + ", temperature=" + temperature + ", humidity=" + humidity - + ", timestamp=" + timestamp + "]"; - } - - -} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/db/DataAccessObject.java b/backend/src/main/java/net/miarma/contaminus/db/DataAccessObject.java new file mode 100644 index 0000000..c75bdae --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/db/DataAccessObject.java @@ -0,0 +1,13 @@ +package net.miarma.contaminus.db; + +import java.util.List; + +import io.vertx.core.Future; + +public interface DataAccessObject { + Future> getAll(); + Future getById(ID id); + Future insert(T t); + Future update(T t); + Future delete(ID id); +} diff --git a/backend/src/main/java/net/miarma/contaminus/db/DatabaseManager.java b/backend/src/main/java/net/miarma/contaminus/db/DatabaseManager.java new file mode 100644 index 0000000..d6370ac --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/db/DatabaseManager.java @@ -0,0 +1,82 @@ +package net.miarma.contaminus.db; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.sqlclient.Pool; +import io.vertx.sqlclient.Row; +import io.vertx.sqlclient.RowSet; +import net.miarma.contaminus.common.Constants; + +public class DatabaseManager { + + private static DatabaseManager instance; + private final Pool pool; + + private DatabaseManager(Pool pool) { + this.pool = pool; + } + + public static synchronized DatabaseManager getInstance(Pool pool) { + if (instance == null) { + instance = new DatabaseManager(pool); + } + return instance; + } + + public Pool getPool() { + return pool; + } + + public Future> testConnection() { + return pool.query("SELECT 1").execute(); + } + + public Future> execute(String query, Class clazz, Handler> onSuccess, + Handler onFailure) { + return pool.query(query).execute().map(rows -> { + List results = new ArrayList<>(); + for (Row row : rows) { + try { + Constructor constructor = clazz.getConstructor(Row.class); + results.add(constructor.newInstance(row)); + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException + | InvocationTargetException e) { + Constants.LOGGER.error("Error instantiating class: " + e.getMessage()); + } + } + return results; + }).onComplete(ar -> { + if (ar.succeeded()) { + onSuccess.handle(ar.result()); + } else { + onFailure.handle(ar.cause()); + } + }); + } + + public Future executeOne(String query, Class clazz, Handler onSuccess, Handler onFailure) { + return pool.query(query).execute().map(rows -> { + for (Row row : rows) { + try { + Constructor constructor = clazz.getConstructor(Row.class); + return constructor.newInstance(row); + } catch (Exception e) { + Constants.LOGGER.error("Error instantiating class: " + e.getMessage()); + } + } + return null; // Si no hay filas + }).onComplete(ar -> { + if (ar.succeeded()) { + onSuccess.handle(ar.result()); + } else { + onFailure.handle(ar.cause()); + } + }); + } + +} diff --git a/backend/src/main/java/net/miarma/contaminus/db/DatabaseProvider.java b/backend/src/main/java/net/miarma/contaminus/db/DatabaseProvider.java new file mode 100644 index 0000000..56af47e --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/db/DatabaseProvider.java @@ -0,0 +1,21 @@ +package net.miarma.contaminus.db; + +import io.vertx.core.Vertx; +import io.vertx.mysqlclient.MySQLConnectOptions; +import io.vertx.sqlclient.Pool; +import io.vertx.sqlclient.PoolOptions; +import net.miarma.contaminus.common.ConfigManager; + +public class DatabaseProvider { + public static Pool createPool(Vertx vertx, ConfigManager config) { + MySQLConnectOptions connectOptions = new MySQLConnectOptions() + .setPort(config.getIntProperty("db.port")) + .setHost(config.getStringProperty("db.host")) + .setDatabase(config.getStringProperty("db.name")) + .setUser(config.getStringProperty("db.user")) + .setPassword(config.getStringProperty("db.password")); + + PoolOptions poolOptions = new PoolOptions().setMaxSize(10); + return Pool.pool(vertx, connectOptions, poolOptions); + } +} diff --git a/backend/src/main/java/net/miarma/contaminus/db/QueryBuilder.java b/backend/src/main/java/net/miarma/contaminus/db/QueryBuilder.java new file mode 100644 index 0000000..30f2ec1 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/db/QueryBuilder.java @@ -0,0 +1,357 @@ +package net.miarma.contaminus.db; + +import java.lang.reflect.Field; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.StringJoiner; +import java.util.stream.Collectors; + +import net.miarma.contaminus.common.Constants; +import net.miarma.contaminus.common.Table; + + +public class QueryBuilder { + private final StringBuilder query; + private String sort; + private String order; + private String limit; + private Class entityClass; + + public QueryBuilder() { + this.query = new StringBuilder(); + } + + private static String getTableName(Class clazz) { + if (clazz == null) { + throw new IllegalArgumentException("Class cannot be null"); + } + + if (clazz.isAnnotationPresent(Table.class)) { + Table annotation = clazz.getAnnotation(Table.class); + return annotation.value(); + } + throw new IllegalArgumentException("Class does not have @Table annotation"); + } + + public String getQuery() { + return query.toString(); + } + + private static Object extractValue(Object fieldValue) { + if (fieldValue instanceof Enum) { + try { + var method = fieldValue.getClass().getMethod("getValue"); + return method.invoke(fieldValue); + } catch (Exception e) { + return ((Enum) fieldValue).name(); + } + } + return fieldValue; + } + + public static QueryBuilder select(Class clazz, String... columns) { + if (clazz == null) { + throw new IllegalArgumentException("Class cannot be null"); + } + + QueryBuilder qb = new QueryBuilder(); + qb.entityClass = clazz; + String tableName = getTableName(clazz); + + qb.query.append("SELECT "); + + if (columns.length == 0) { + qb.query.append("* "); + } else { + StringJoiner joiner = new StringJoiner(", "); + for (String column : columns) { + if (column != null) { + joiner.add(column); + } + } + qb.query.append(joiner).append(" "); + } + + qb.query.append("FROM ").append(tableName).append(" "); + return qb; + } + + public QueryBuilder where(Map filters) { + if (filters == null || filters.isEmpty()) { + return this; + } + + Set validFields = entityClass != null + ? Arrays.stream(entityClass.getDeclaredFields()).map(Field::getName).collect(Collectors.toSet()) + : Collections.emptySet(); + + List conditions = new ArrayList<>(); + + for (Map.Entry entry : filters.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + + if (!validFields.contains(key)) { + Constants.LOGGER.warn("[QueryBuilder] Ignorando campo invalido en WHERE: " + key); + continue; + } + + if (value.startsWith("(") && value.endsWith(")")) { + conditions.add(key + " IN " + value); + } else if (value.matches("-?\\d+(\\.\\d+)?")) { + conditions.add(key + " = " + value); + } else { + conditions.add(key + " = '" + value + "'"); + } + } + + if (!conditions.isEmpty()) { + query.append("WHERE ").append(String.join(" AND ", conditions)).append(" "); + } + + return this; + } + + public QueryBuilder where(T object) { + if (object == null) { + throw new IllegalArgumentException("Object cannot be null"); + } + + Set validFields = entityClass != null + ? Arrays.stream(entityClass.getDeclaredFields()).map(Field::getName).collect(Collectors.toSet()) + : Collections.emptySet(); + + List conditions = new ArrayList<>(); + for (Field field : object.getClass().getDeclaredFields()) { + field.setAccessible(true); + try { + Object fieldValue = field.get(object); + if (fieldValue != null) { + String key = field.getName(); + if (!validFields.contains(key)) { + Constants.LOGGER.warn("[QueryBuilder] Ignorando campo invalido en WHERE: " + key); + continue; + } + Object value = extractValue(fieldValue); + if (value instanceof String || value instanceof LocalDateTime) { + conditions.add(key + " = '" + value + "'"); + } else { + conditions.add(key + " = " + value); + } + } + } catch (IllegalArgumentException | IllegalAccessException e) { + Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); + } + } + + if (!conditions.isEmpty()) { + query.append("WHERE ").append(String.join(" AND ", conditions)).append(" "); + } + + return this; + } + + + public static QueryBuilder insert(T object) { + if (object == null) { + throw new IllegalArgumentException("Object cannot be null"); + } + + QueryBuilder qb = new QueryBuilder(); + String table = getTableName(object.getClass()); + qb.query.append("INSERT INTO ").append(table).append(" "); + qb.query.append("("); + StringJoiner columns = new StringJoiner(", "); + StringJoiner values = new StringJoiner(", "); + for (Field field : object.getClass().getDeclaredFields()) { + field.setAccessible(true); + try { + columns.add(field.getName()); + Object fieldValue = field.get(object); + if (fieldValue != null) { + Object value = extractValue(fieldValue); + if (value instanceof String || value instanceof LocalDateTime) { + values.add("'" + value + "'"); + } else { + values.add(value.toString()); + } + } else { + values.add("NULL"); + } + } catch (IllegalArgumentException | IllegalAccessException e) { + Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); + } + } + qb.query.append(columns).append(") "); + qb.query.append("VALUES (").append(values).append(") RETURNING * "); + return qb; + } + + public static QueryBuilder update(T object) { + if (object == null) { + throw new IllegalArgumentException("Object cannot be null"); + } + + QueryBuilder qb = new QueryBuilder(); + String table = getTableName(object.getClass()); + qb.query.append("UPDATE ").append(table).append(" SET "); + + StringJoiner setJoiner = new StringJoiner(", "); + StringJoiner whereJoiner = new StringJoiner(" AND "); + + Field idField = null; + + for (Field field : object.getClass().getDeclaredFields()) { + field.setAccessible(true); + try { + Object fieldValue = field.get(object); + if (fieldValue == null) continue; + + String fieldName = field.getName(); + Object value = extractValue(fieldValue); + + if (fieldName.endsWith("_id")) { + idField = field; + whereJoiner.add(fieldName + " = " + (value instanceof String + || value instanceof LocalDateTime ? "'" + value + "'" : value)); + continue; + } + + setJoiner.add(fieldName + " = " + (value instanceof String + || value instanceof LocalDateTime ? "'" + value + "'" : value)); + } catch (Exception e) { + Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); + } + } + + if (idField == null) { + throw new IllegalArgumentException("No ID field (ending with _id) found for WHERE clause"); + } + + qb.query.append(setJoiner).append(" WHERE ").append(whereJoiner); + return qb; + } + + public static QueryBuilder updateWithNulls(T object) { + if (object == null) { + throw new IllegalArgumentException("Object cannot be null"); + } + + QueryBuilder qb = new QueryBuilder(); + String table = getTableName(object.getClass()); + qb.query.append("UPDATE ").append(table).append(" SET "); + + StringJoiner setJoiner = new StringJoiner(", "); + StringJoiner whereJoiner = new StringJoiner(" AND "); + + Field idField = null; + + for (Field field : object.getClass().getDeclaredFields()) { + field.setAccessible(true); + try { + String fieldName = field.getName(); + Object fieldValue = field.get(object); + + if (fieldName.endsWith("_id")) { + idField = field; + Object value = extractValue(fieldValue); + whereJoiner.add(fieldName + " = " + (value instanceof String || value instanceof LocalDateTime ? "'" + value + "'" : value)); + continue; + } + + if (fieldValue == null) { + setJoiner.add(fieldName + " = NULL"); // ✅ esto lo borra en la BD + } else { + Object value = extractValue(fieldValue); + setJoiner.add(fieldName + " = " + (value instanceof String || value instanceof LocalDateTime ? "'" + value + "'" : value)); + } + } catch (Exception e) { + Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); + } + } + + if (idField == null) { + throw new IllegalArgumentException("No ID field (ending with _id) found for WHERE clause"); + } + + qb.query.append(setJoiner).append(" WHERE ").append(whereJoiner); + return qb; + } + + + public static QueryBuilder delete(T object) { + if (object == null) throw new IllegalArgumentException("Object cannot be null"); + + QueryBuilder qb = new QueryBuilder(); + String table = getTableName(object.getClass()); + qb.query.append("DELETE FROM ").append(table).append(" WHERE "); + + StringJoiner joiner = new StringJoiner(" AND "); + for (Field field : object.getClass().getDeclaredFields()) { + field.setAccessible(true); + try { + Object fieldValue = field.get(object); + if (fieldValue != null) { + Object value = extractValue(fieldValue); + joiner.add(field.getName() + " = " + (value instanceof String + || value instanceof LocalDateTime ? "'" + value + "'" : value.toString())); + } + } catch (Exception e) { + Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); + } + } + + qb.query.append(joiner).append(" "); + return qb; + } + + public QueryBuilder orderBy(Optional column, Optional order) { + column.ifPresent(c -> { + if (entityClass != null) { + boolean isValid = Arrays.stream(entityClass.getDeclaredFields()) + .map(Field::getName) + .anyMatch(f -> f.equals(c)); + + if (!isValid) { + Constants.LOGGER.warn("[QueryBuilder] Ignorando campo invalido en ORDER BY: " + c); + return; + } + } + + sort = "ORDER BY " + c + " "; + order.ifPresent(o -> { + sort += o.equalsIgnoreCase("asc") ? "ASC" : "DESC" + " "; + }); + }); + return this; + } + + public QueryBuilder limit(Optional limitParam) { + limitParam.ifPresent(param -> limit = "LIMIT " + param + " "); + return this; + } + + public QueryBuilder offset(Optional offsetParam) { + offsetParam.ifPresent(param -> limit += "OFFSET " + param + " "); + return this; + } + + public String build() { + if (order != null && !order.isEmpty()) { + query.append(order); + } + if (sort != null && !sort.isEmpty()) { + query.append(sort); + } + if (limit != null && !limit.isEmpty()) { + query.append(limit); + } + return query.toString().trim() + ";"; + } +} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/Actuator.java b/backend/src/main/java/net/miarma/contaminus/entities/Actuator.java similarity index 93% rename from backend/src/main/java/net/miarma/contaminus/database/entities/Actuator.java rename to backend/src/main/java/net/miarma/contaminus/entities/Actuator.java index d121e0e..74e0a0f 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/Actuator.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/Actuator.java @@ -1,92 +1,92 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("actuators") -public class Actuator { - - private Integer actuatorId; - private String deviceId; - private Integer status; - private Long timestamp; - - public Actuator() {} - - public Actuator(Row row) { - this.actuatorId = row.getInteger("actuatorId"); - this.deviceId = row.getString("deviceId"); - this.status = row.getInteger("status"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public Actuator(Integer actuatorId, String deviceId, Integer status, Long timestamp) { - super(); - this.actuatorId = actuatorId; - this.deviceId = deviceId; - this.status = status; - this.timestamp = timestamp; - } - - public Integer getActuatorId() { - return actuatorId; - } - - public void setActuatorId(Integer actuatorId) { - this.actuatorId = actuatorId; - } - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public Long getTimestamp() { - return timestamp; - } - - public void setTimestamp(Long timestamp) { - this.timestamp = timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(actuatorId, deviceId, status, timestamp); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Actuator other = (Actuator) obj; - return actuatorId == other.actuatorId && deviceId == other.deviceId - && status == other.status && timestamp == other.timestamp; - } - - @Override - public String toString() { - return "Actuator [actuatorId=" + actuatorId + ", deviceId=" + deviceId + ", status=" + status + ", timestamp=" - + timestamp + "]"; - } - - - +package net.miarma.contaminus.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.util.DateParser; + +@Table("actuators") +public class Actuator { + + private Integer actuatorId; + private String deviceId; + private Integer status; + private Long timestamp; + + public Actuator() {} + + public Actuator(Row row) { + this.actuatorId = row.getInteger("actuatorId"); + this.deviceId = row.getString("deviceId"); + this.status = row.getInteger("status"); + this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); + } + + public Actuator(Integer actuatorId, String deviceId, Integer status, Long timestamp) { + super(); + this.actuatorId = actuatorId; + this.deviceId = deviceId; + this.status = status; + this.timestamp = timestamp; + } + + public Integer getActuatorId() { + return actuatorId; + } + + public void setActuatorId(Integer actuatorId) { + this.actuatorId = actuatorId; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(actuatorId, deviceId, status, timestamp); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Actuator other = (Actuator) obj; + return actuatorId == other.actuatorId && deviceId == other.deviceId + && status == other.status && timestamp == other.timestamp; + } + + @Override + public String toString() { + return "Actuator [actuatorId=" + actuatorId + ", deviceId=" + deviceId + ", status=" + status + ", timestamp=" + + timestamp + "]"; + } + + + } \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/COValue.java b/backend/src/main/java/net/miarma/contaminus/entities/COValue.java similarity index 94% rename from backend/src/main/java/net/miarma/contaminus/database/entities/COValue.java rename to backend/src/main/java/net/miarma/contaminus/entities/COValue.java index a0343f2..2d52bdc 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/COValue.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/COValue.java @@ -1,107 +1,107 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("co_values") -public class COValue { - - private Integer valueId; - private String deviceId; - private Integer sensorId; - private Float value; - private Long timestamp; - - public COValue() {} - - public COValue(Row row) { - this.valueId = row.getInteger("valueId"); - this.deviceId = row.getString("deviceId"); - this.sensorId = row.getInteger("sensorId"); - this.value = row.getFloat("value"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public COValue(Integer valueId, String deviceId, Integer sensorId, Float value, Long timestamp) { - super(); - this.valueId = valueId; - this.deviceId = deviceId; - this.sensorId = sensorId; - this.value = value; - this.timestamp = timestamp; - } - - public Integer getValueId() { - return valueId; - } - - public void setValueId(Integer valueId) { - this.valueId = valueId; - } - +package net.miarma.contaminus.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.util.DateParser; + +@Table("co_values") +public class COValue { + + private Integer valueId; + private String deviceId; + private Integer sensorId; + private Float value; + private Long timestamp; + + public COValue() {} + + public COValue(Row row) { + this.valueId = row.getInteger("valueId"); + this.deviceId = row.getString("deviceId"); + this.sensorId = row.getInteger("sensorId"); + this.value = row.getFloat("value"); + this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); + } + + public COValue(Integer valueId, String deviceId, Integer sensorId, Float value, Long timestamp) { + super(); + this.valueId = valueId; + this.deviceId = deviceId; + this.sensorId = sensorId; + this.value = value; + this.timestamp = timestamp; + } + + public Integer getValueId() { + return valueId; + } + + public void setValueId(Integer valueId) { + this.valueId = valueId; + } + public String getDeviceId() { return deviceId; - } - + } + public void setDeviceId(String deviceId) { this.deviceId = deviceId; - } - - public Integer getSensorId() { - return sensorId; - } - - public void setSensorId(Integer sensorId) { - this.sensorId = sensorId; - } - - public Float getValue() { - return value; - } - - public void setValue(Float value) { - this.value = value; - } - - public Long getTimestamp() { - return timestamp; - } - - public void setTimestamp(Long timestamp) { - this.timestamp = timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(deviceId, sensorId, timestamp, value, valueId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - COValue other = (COValue) obj; - return Objects.equals(deviceId, other.deviceId) && Objects.equals(sensorId, other.sensorId) - && Objects.equals(timestamp, other.timestamp) && Objects.equals(value, other.value) - && Objects.equals(valueId, other.valueId); - } - - @Override - public String toString() { - return "COValue [valueId=" + valueId + ", deviceId=" + deviceId + ", sensorId=" + sensorId + ", value=" + value - + ", timestamp=" + timestamp + "]"; - } - + } + + public Integer getSensorId() { + return sensorId; + } + + public void setSensorId(Integer sensorId) { + this.sensorId = sensorId; + } + + public Float getValue() { + return value; + } + + public void setValue(Float value) { + this.value = value; + } + + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(deviceId, sensorId, timestamp, value, valueId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + COValue other = (COValue) obj; + return Objects.equals(deviceId, other.deviceId) && Objects.equals(sensorId, other.sensorId) + && Objects.equals(timestamp, other.timestamp) && Objects.equals(value, other.value) + && Objects.equals(valueId, other.valueId); + } + + @Override + public String toString() { + return "COValue [valueId=" + valueId + ", deviceId=" + deviceId + ", sensorId=" + sensorId + ", value=" + value + + ", timestamp=" + timestamp + "]"; + } + public static COValue fromPayload(DevicePayload payload) { return new COValue(null, payload.getDeviceId(), payload.getSensorId(), payload.getCarbonMonoxide(), payload.getTimestamp()); - } - - + } + + } \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/Device.java b/backend/src/main/java/net/miarma/contaminus/entities/Device.java similarity index 91% rename from backend/src/main/java/net/miarma/contaminus/database/entities/Device.java rename to backend/src/main/java/net/miarma/contaminus/entities/Device.java index 81d1f4c..3861c20 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/Device.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/Device.java @@ -1,57 +1,57 @@ -package net.miarma.contaminus.database.entities; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; - -@Table("devices") -public class Device { - - private String deviceId; - private Integer groupId; - private String deviceName; - - public Device() {} - - public Device(Row row) { - this.deviceId = row.getString("deviceId"); - this.groupId = row.getInteger("groupId"); - this.deviceName = row.getString("deviceName"); - } - - public Device(String deviceId, Integer groupId, String deviceName) { - super(); - this.deviceId = deviceId; - this.groupId = groupId; - this.deviceName = deviceName; - } - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public Integer getGroupId() { - return groupId; - } - - public void setGroupId(Integer groupId) { - this.groupId = groupId; - } - - public String getDeviceName() { - return deviceName; - } - - public void setDeviceName(String deviceName) { - this.deviceName = deviceName; - } - - - - - -} - +package net.miarma.contaminus.entities; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; + +@Table("devices") +public class Device { + + private String deviceId; + private Integer groupId; + private String deviceName; + + public Device() {} + + public Device(Row row) { + this.deviceId = row.getString("deviceId"); + this.groupId = row.getInteger("groupId"); + this.deviceName = row.getString("deviceName"); + } + + public Device(String deviceId, Integer groupId, String deviceName) { + super(); + this.deviceId = deviceId; + this.groupId = groupId; + this.deviceName = deviceName; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public Integer getGroupId() { + return groupId; + } + + public void setGroupId(Integer groupId) { + this.groupId = groupId; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + + + + +} + diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/DevicePayload.java b/backend/src/main/java/net/miarma/contaminus/entities/DevicePayload.java similarity index 95% rename from backend/src/main/java/net/miarma/contaminus/database/entities/DevicePayload.java rename to backend/src/main/java/net/miarma/contaminus/entities/DevicePayload.java index a470ba5..70a714f 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/DevicePayload.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/DevicePayload.java @@ -1,130 +1,130 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -public class DevicePayload { - private String deviceId; - private Integer sensorId; - private Float temperature; - private Float humidity; - private Float pressure; - private Float carbonMonoxide; - private Float lat; - private Float lon; - private Long timestamp; - - public DevicePayload() {} - +package net.miarma.contaminus.entities; + +import java.util.Objects; + +public class DevicePayload { + private String deviceId; + private Integer sensorId; + private Float temperature; + private Float humidity; + private Float pressure; + private Float carbonMonoxide; + private Float lat; + private Float lon; + private Long timestamp; + + public DevicePayload() {} + public DevicePayload(String deviceId, Integer sensorId, String sensorType, String unit, Integer sensorStatus, Float temperature, Float humidity, Float pressure, Float carbonMonoxide, Float lat, Float lon, Long timestamp) { super(); this.deviceId = deviceId; this.sensorId = sensorId; this.temperature = temperature; - this.humidity = humidity; + this.humidity = humidity; this.pressure = pressure; this.carbonMonoxide = carbonMonoxide; this.lat = lat; this.lon = lon; this.timestamp = timestamp; - } - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public Integer getSensorId() { - return sensorId; - } - - public void setSensorId(Integer sensorId) { - this.sensorId = sensorId; - } - - public Float getTemperature() { - return temperature; - } - - public void setTemperature(Float temperature) { - this.temperature = temperature; - } - - public Float getHumidity() { - return humidity; - } - - public void setHumidity(Float humidity) { - this.humidity = humidity; - } - + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public Integer getSensorId() { + return sensorId; + } + + public void setSensorId(Integer sensorId) { + this.sensorId = sensorId; + } + + public Float getTemperature() { + return temperature; + } + + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + public Float getHumidity() { + return humidity; + } + + public void setHumidity(Float humidity) { + this.humidity = humidity; + } + public Float getPressure() { return pressure; - } - - public Float getCarbonMonoxide() { - return carbonMonoxide; - } - - public void setCarbonMonoxide(Float carbonMonoxide) { - this.carbonMonoxide = carbonMonoxide; - } - - public Float getLat() { - return lat; - } - - public void setLat(Float lat) { - this.lat = lat; - } - - public Float getLon() { - return lon; - } - - public void setLon(Float lon) { - this.lon = lon; - } - - public Long getTimestamp() { - return timestamp; - } - - public void setTimestamp(Long timestamp) { - this.timestamp = timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(carbonMonoxide, deviceId, humidity, lat, lon, pressure, sensorId, temperature, timestamp); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DevicePayload other = (DevicePayload) obj; - return Objects.equals(carbonMonoxide, other.carbonMonoxide) && Objects.equals(deviceId, other.deviceId) - && Objects.equals(humidity, other.humidity) && Objects.equals(lat, other.lat) - && Objects.equals(lon, other.lon) && Objects.equals(pressure, other.pressure) - && Objects.equals(sensorId, other.sensorId) && Objects.equals(temperature, other.temperature) - && Objects.equals(timestamp, other.timestamp); - } - - @Override - public String toString() { - return "DevicePayload [deviceId=" + deviceId + ", sensorId=" + sensorId + ", temperature=" + temperature - + ", humidity=" + humidity + ", pressure=" + pressure + ", carbonMonoxide=" + carbonMonoxide + ", lat=" - + lat + ", lon=" + lon + ", timestamp=" + timestamp + "]"; - } - - - -} + } + + public Float getCarbonMonoxide() { + return carbonMonoxide; + } + + public void setCarbonMonoxide(Float carbonMonoxide) { + this.carbonMonoxide = carbonMonoxide; + } + + public Float getLat() { + return lat; + } + + public void setLat(Float lat) { + this.lat = lat; + } + + public Float getLon() { + return lon; + } + + public void setLon(Float lon) { + this.lon = lon; + } + + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(carbonMonoxide, deviceId, humidity, lat, lon, pressure, sensorId, temperature, timestamp); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DevicePayload other = (DevicePayload) obj; + return Objects.equals(carbonMonoxide, other.carbonMonoxide) && Objects.equals(deviceId, other.deviceId) + && Objects.equals(humidity, other.humidity) && Objects.equals(lat, other.lat) + && Objects.equals(lon, other.lon) && Objects.equals(pressure, other.pressure) + && Objects.equals(sensorId, other.sensorId) && Objects.equals(temperature, other.temperature) + && Objects.equals(timestamp, other.timestamp); + } + + @Override + public String toString() { + return "DevicePayload [deviceId=" + deviceId + ", sensorId=" + sensorId + ", temperature=" + temperature + + ", humidity=" + humidity + ", pressure=" + pressure + ", carbonMonoxide=" + carbonMonoxide + ", lat=" + + lat + ", lon=" + lon + ", timestamp=" + timestamp + "]"; + } + + + +} diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/GpsValue.java b/backend/src/main/java/net/miarma/contaminus/entities/GpsValue.java similarity index 94% rename from backend/src/main/java/net/miarma/contaminus/database/entities/GpsValue.java rename to backend/src/main/java/net/miarma/contaminus/entities/GpsValue.java index dbbfd22..ae8e056 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/GpsValue.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/GpsValue.java @@ -1,118 +1,118 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("gps_values") -public class GpsValue { - - private Integer valueId; - private String deviceId; - private Integer sensorId; - private Float lat; - private Float lon; - private Long timestamp; - - public GpsValue() {} - - public GpsValue(Row row) { - this.valueId = row.getInteger("valueId"); - this.deviceId = row.getString("deviceId"); - this.sensorId = row.getInteger("sensorId"); - this.lat = row.getFloat("lat"); - this.lon = row.getFloat("lon"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public GpsValue(Integer valueId, String deviceId, Integer sensorId, Float lat, Float lon, Long timestamp) { - super(); - this.valueId = valueId; - this.deviceId = deviceId; - this.sensorId = sensorId; - this.lat = lat; - this.lon = lon; - this.timestamp = timestamp; - } - - public Integer getValueId() { - return valueId; - } - - public void setValueId(Integer valueId) { - this.valueId = valueId; - } - +package net.miarma.contaminus.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.util.DateParser; + +@Table("gps_values") +public class GpsValue { + + private Integer valueId; + private String deviceId; + private Integer sensorId; + private Float lat; + private Float lon; + private Long timestamp; + + public GpsValue() {} + + public GpsValue(Row row) { + this.valueId = row.getInteger("valueId"); + this.deviceId = row.getString("deviceId"); + this.sensorId = row.getInteger("sensorId"); + this.lat = row.getFloat("lat"); + this.lon = row.getFloat("lon"); + this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); + } + + public GpsValue(Integer valueId, String deviceId, Integer sensorId, Float lat, Float lon, Long timestamp) { + super(); + this.valueId = valueId; + this.deviceId = deviceId; + this.sensorId = sensorId; + this.lat = lat; + this.lon = lon; + this.timestamp = timestamp; + } + + public Integer getValueId() { + return valueId; + } + + public void setValueId(Integer valueId) { + this.valueId = valueId; + } + public String getDeviceId() { return deviceId; - } - + } + public void setDeviceId(String deviceId) { this.deviceId = deviceId; - } - - public Integer getSensorId() { - return sensorId; - } - - public void setSensorId(Integer sensorId) { - this.sensorId = sensorId; - } - - public Float getLat() { - return lat; - } - - public void setLat(Float lat) { - this.lat = lat; - } - - public Float getLon() { - return lon; - } - - public void setLon(Float lon) { - this.lon = lon; - } - - public Long getTimestamp() { - return timestamp; - } - - public void setTimestamp(Long timestamp) { - this.timestamp = timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(deviceId, lat, lon, sensorId, timestamp, valueId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - GpsValue other = (GpsValue) obj; - return Objects.equals(deviceId, other.deviceId) && Objects.equals(lat, other.lat) - && Objects.equals(lon, other.lon) && Objects.equals(sensorId, other.sensorId) - && Objects.equals(timestamp, other.timestamp) && Objects.equals(valueId, other.valueId); - } - - @Override - public String toString() { - return "GpsValue [valueId=" + valueId + ", deviceId=" + deviceId + ", sensorId=" + sensorId + ", lat=" + lat - + ", lon=" + lon + ", timestamp=" + timestamp + "]"; - } - + } + + public Integer getSensorId() { + return sensorId; + } + + public void setSensorId(Integer sensorId) { + this.sensorId = sensorId; + } + + public Float getLat() { + return lat; + } + + public void setLat(Float lat) { + this.lat = lat; + } + + public Float getLon() { + return lon; + } + + public void setLon(Float lon) { + this.lon = lon; + } + + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(deviceId, lat, lon, sensorId, timestamp, valueId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + GpsValue other = (GpsValue) obj; + return Objects.equals(deviceId, other.deviceId) && Objects.equals(lat, other.lat) + && Objects.equals(lon, other.lon) && Objects.equals(sensorId, other.sensorId) + && Objects.equals(timestamp, other.timestamp) && Objects.equals(valueId, other.valueId); + } + + @Override + public String toString() { + return "GpsValue [valueId=" + valueId + ", deviceId=" + deviceId + ", sensorId=" + sensorId + ", lat=" + lat + + ", lon=" + lon + ", timestamp=" + timestamp + "]"; + } + public static GpsValue fromPayload(DevicePayload payload) { return new GpsValue(null, payload.getDeviceId(), payload.getSensorId(), payload.getLat(), payload.getLon(), payload.getTimestamp()); - } - + } + } \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/Group.java b/backend/src/main/java/net/miarma/contaminus/entities/Group.java similarity index 92% rename from backend/src/main/java/net/miarma/contaminus/database/entities/Group.java rename to backend/src/main/java/net/miarma/contaminus/entities/Group.java index 056b78b..9c2fa2c 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/Group.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/Group.java @@ -1,66 +1,66 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; - -@Table("groups") -public class Group { - - private Integer groupId; - private String groupName; - - public Group() {} - - public Group(Row row) { - this.groupId = row.getInteger("groupId"); - this.groupName = row.getString("groupName"); - } - - public Group(Integer groupId, String groupName) { - super(); - this.groupId = groupId; - this.groupName = groupName; - } - - public Integer getGroupId() { - return groupId; - } - - public void setGroupId(Integer groupId) { - this.groupId = groupId; - } - - public String getGroupName() { - return groupName; - } - - public void setGroupName(String groupName) { - this.groupName = groupName; - } - - @Override - public int hashCode() { - return Objects.hash(groupId, groupName); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Group other = (Group) obj; - return Objects.equals(groupId, other.groupId) && Objects.equals(groupName, other.groupName); - } - - @Override - public String toString() { - return "Group [groupId=" + groupId + ", groupName=" + groupName + "]"; - } - - +package net.miarma.contaminus.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; + +@Table("groups") +public class Group { + + private Integer groupId; + private String groupName; + + public Group() {} + + public Group(Row row) { + this.groupId = row.getInteger("groupId"); + this.groupName = row.getString("groupName"); + } + + public Group(Integer groupId, String groupName) { + super(); + this.groupId = groupId; + this.groupName = groupName; + } + + public Integer getGroupId() { + return groupId; + } + + public void setGroupId(Integer groupId) { + this.groupId = groupId; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + @Override + public int hashCode() { + return Objects.hash(groupId, groupName); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Group other = (Group) obj; + return Objects.equals(groupId, other.groupId) && Objects.equals(groupName, other.groupName); + } + + @Override + public String toString() { + return "Group [groupId=" + groupId + ", groupName=" + groupName + "]"; + } + + } \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/Sensor.java b/backend/src/main/java/net/miarma/contaminus/entities/Sensor.java similarity index 94% rename from backend/src/main/java/net/miarma/contaminus/database/entities/Sensor.java rename to backend/src/main/java/net/miarma/contaminus/entities/Sensor.java index ba0e08f..e39b9db 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/Sensor.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/Sensor.java @@ -1,114 +1,114 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("sensors") -public class Sensor { - - private Integer sensorId; - private String deviceId; - private String sensorType; - private String unit; - private Integer status; - private Long timestamp; - - public Sensor() {} - - public Sensor(Row row) { - this.sensorId = row.getInteger("sensorId"); - this.deviceId = row.getString("deviceId"); - this.sensorType = row.getString("sensorType"); - this.unit = row.getString("unit"); - this.status = row.getInteger("status"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public Sensor(Integer sensorId, String deviceId, String sensorType, String unit, Integer status, Long timestamp) { - super(); - this.sensorId = sensorId; - this.deviceId = deviceId; - this.sensorType = sensorType; - this.unit = unit; - this.status = status; - this.timestamp = timestamp; - } - - public Integer getSensorId() { - return sensorId; - } - - public void setSensorId(Integer sensorId) { - this.sensorId = sensorId; - } - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public String getSensorType() { - return sensorType; - } - - public void setSensorType(String sensorType) { - this.sensorType = sensorType; - } - - public String getUnit() { - return unit; - } - - public void setUnit(String unit) { - this.unit = unit; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public Long getTimestamp() { - return timestamp; - } - - public void setTimestamp(Long timestamp) { - this.timestamp = timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(deviceId, sensorId, sensorType, status, timestamp, unit); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Sensor other = (Sensor) obj; - return Objects.equals(deviceId, other.deviceId) && Objects.equals(sensorId, other.sensorId) - && Objects.equals(sensorType, other.sensorType) && Objects.equals(status, other.status) - && Objects.equals(timestamp, other.timestamp) && Objects.equals(unit, other.unit); - } - - @Override - public String toString() { - return "Sensor [sensorId=" + sensorId + ", deviceId=" + deviceId + ", sensorType=" + sensorType + ", unit=" - + unit + ", status=" + status + ", timestamp=" + timestamp + "]"; - } - - -} +package net.miarma.contaminus.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.util.DateParser; + +@Table("sensors") +public class Sensor { + + private Integer sensorId; + private String deviceId; + private String sensorType; + private String unit; + private Integer status; + private Long timestamp; + + public Sensor() {} + + public Sensor(Row row) { + this.sensorId = row.getInteger("sensorId"); + this.deviceId = row.getString("deviceId"); + this.sensorType = row.getString("sensorType"); + this.unit = row.getString("unit"); + this.status = row.getInteger("status"); + this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); + } + + public Sensor(Integer sensorId, String deviceId, String sensorType, String unit, Integer status, Long timestamp) { + super(); + this.sensorId = sensorId; + this.deviceId = deviceId; + this.sensorType = sensorType; + this.unit = unit; + this.status = status; + this.timestamp = timestamp; + } + + public Integer getSensorId() { + return sensorId; + } + + public void setSensorId(Integer sensorId) { + this.sensorId = sensorId; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getSensorType() { + return sensorType; + } + + public void setSensorType(String sensorType) { + this.sensorType = sensorType; + } + + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(deviceId, sensorId, sensorType, status, timestamp, unit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Sensor other = (Sensor) obj; + return Objects.equals(deviceId, other.deviceId) && Objects.equals(sensorId, other.sensorId) + && Objects.equals(sensorType, other.sensorType) && Objects.equals(status, other.status) + && Objects.equals(timestamp, other.timestamp) && Objects.equals(unit, other.unit); + } + + @Override + public String toString() { + return "Sensor [sensorId=" + sensorId + ", deviceId=" + deviceId + ", sensorType=" + sensorType + ", unit=" + + unit + ", status=" + status + ", timestamp=" + timestamp + "]"; + } + + +} diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceLatestValuesView.java b/backend/src/main/java/net/miarma/contaminus/entities/ViewLatestValues.java similarity index 58% rename from backend/src/main/java/net/miarma/contaminus/database/entities/DeviceLatestValuesView.java rename to backend/src/main/java/net/miarma/contaminus/entities/ViewLatestValues.java index a163bd3..6d46abe 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceLatestValuesView.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/ViewLatestValues.java @@ -1,142 +1,201 @@ -package net.miarma.contaminus.database.entities; -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("v_latest_values") -public class DeviceLatestValuesView { - private String deviceId; - private Integer sensorId; - private String sensorType; - private String unit; - private Integer sensorStatus; - private Long sensorTimestamp; - private Float temperature; - private Float humidity; - private Float carbonMonoxide; - private Float lat; - private Float lon; - private Long airValuesTimestamp; - - public DeviceLatestValuesView() {} - - public DeviceLatestValuesView(Row row) { - this.deviceId = row.getString("deviceId"); - this.sensorId = row.getInteger("sensorId"); - this.sensorType = row.getString("sensorType"); - this.unit = row.getString("unit"); - this.sensorStatus = row.getInteger("sensorStatus"); - this.sensorTimestamp = DateParser.parseDate(row.getLocalDateTime("sensorTimestamp")); - this.temperature = row.getFloat("temperature"); - this.humidity = row.getFloat("humidity"); - this.carbonMonoxide = row.getFloat("carbonMonoxide"); - this.lat = row.getFloat("lat"); - this.lon = row.getFloat("lon"); - this.airValuesTimestamp = DateParser.parseDate(row.getLocalDateTime("airValuesTimestamp")); - } - - public DeviceLatestValuesView(String deviceId, Integer sensorId, String sensorType, String unit, Integer sensorStatus, - Long sensorTimestamp, Float temperature, Float humidity, Float carbonMonoxide, Float lat, Float lon, - Long airValuesTimestamp) { - super(); - this.deviceId = deviceId; - this.sensorId = sensorId; - this.sensorType = sensorType; - this.unit = unit; - this.sensorStatus = sensorStatus; - this.sensorTimestamp = sensorTimestamp; - this.temperature = temperature; - this.humidity = humidity; - this.carbonMonoxide = carbonMonoxide; - this.lat = lat; - this.lon = lon; - this.airValuesTimestamp = airValuesTimestamp; - } - - public String getDeviceId() { - return deviceId; - } - - public Integer getSensorId() { - return sensorId; - } - - public String getSensorType() { - return sensorType; - } - - public String getUnit() { - return unit; - } - - public Integer getSensorStatus() { - return sensorStatus; - } - - public Long getSensorTimestamp() { - return sensorTimestamp; - } - - public Float getTemperature() { - return temperature; - } - - public Float getHumidity() { - return humidity; - } - - public Float getCarbonMonoxide() { - return carbonMonoxide; - } - - public Float getLat() { - return lat; - } - - public Float getLon() { - return lon; - } - - public Long getAirValuesTimestamp() { - return airValuesTimestamp; - } - - @Override - public int hashCode() { - return Objects.hash(airValuesTimestamp, carbonMonoxide, deviceId, humidity, lat, lon, sensorId, sensorStatus, - sensorTimestamp, sensorType, temperature, unit); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DeviceLatestValuesView other = (DeviceLatestValuesView) obj; - return Objects.equals(airValuesTimestamp, other.airValuesTimestamp) - && Objects.equals(carbonMonoxide, other.carbonMonoxide) && Objects.equals(deviceId, other.deviceId) - && Objects.equals(humidity, other.humidity) && Objects.equals(lat, other.lat) - && Objects.equals(lon, other.lon) && Objects.equals(sensorId, other.sensorId) - && Objects.equals(sensorStatus, other.sensorStatus) - && Objects.equals(sensorTimestamp, other.sensorTimestamp) - && Objects.equals(sensorType, other.sensorType) && Objects.equals(temperature, other.temperature) - && Objects.equals(unit, other.unit); - } - - @Override - public String toString() { - return "DeviceLatestValuesView [deviceId=" + deviceId + ", sensorId=" + sensorId + ", sensorType=" + sensorType - + ", unit=" + unit + ", sensorStatus=" + sensorStatus + ", sensorTimestamp=" + sensorTimestamp - + ", temperature=" + temperature + ", humidity=" + humidity + ", carbonMonoxide=" + carbonMonoxide - + ", lat=" + lat + ", lon=" + lon + ", airValuesTimestamp=" + airValuesTimestamp + "]"; - } - - - - -} +package net.miarma.contaminus.entities; +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.util.DateParser; + +@Table("v_latest_values") +public class ViewLatestValues { + + private String deviceId; + private Integer sensorId; + private String sensorType; + private String unit; + private Integer sensorStatus; + private Long sensorTimestamp; + private Float temperature; + private Float humidity; + private Float pressure; + private Float carbonMonoxide; + private Float lat; + private Float lon; + private Long airValuesTimestamp; + + public ViewLatestValues() {} + + public ViewLatestValues(Row row) { + this.deviceId = row.getString("deviceId"); + this.sensorId = row.getInteger("sensorId"); + this.sensorType = row.getString("sensorType"); + this.unit = row.getString("unit"); + this.sensorStatus = row.getInteger("sensorStatus"); + this.sensorTimestamp = DateParser.parseDate(row.getLocalDateTime("sensorTimestamp")); + this.temperature = row.getFloat("temperature"); + this.humidity = row.getFloat("humidity"); + this.pressure = row.getFloat("pressure"); + this.carbonMonoxide = row.getFloat("carbonMonoxide"); + this.lat = row.getFloat("lat"); + this.lon = row.getFloat("lon"); + this.airValuesTimestamp = DateParser.parseDate(row.getLocalDateTime("airValuesTimestamp")); + } + + public ViewLatestValues(String deviceId, Integer sensorId, String sensorType, String unit, Integer sensorStatus, + Long sensorTimestamp, Float temperature, Float humidity, Float pressure, Float carbonMonoxide, Float lat, Float lon, + Long airValuesTimestamp) { + super(); + this.deviceId = deviceId; + this.sensorId = sensorId; + this.sensorType = sensorType; + this.unit = unit; + this.sensorStatus = sensorStatus; + this.sensorTimestamp = sensorTimestamp; + this.temperature = temperature; + this.humidity = humidity; + this.carbonMonoxide = carbonMonoxide; + this.lat = lat; + this.lon = lon; + this.airValuesTimestamp = airValuesTimestamp; + } + + public String getDeviceId() { + return deviceId; + } + + public Integer getSensorId() { + return sensorId; + } + + public String getSensorType() { + return sensorType; + } + + public String getUnit() { + return unit; + } + + public Integer getSensorStatus() { + return sensorStatus; + } + + public Long getSensorTimestamp() { + return sensorTimestamp; + } + + public Float getTemperature() { + return temperature; + } + + public Float getHumidity() { + return humidity; + } + + public Float getPressure() { + return pressure; + } + + public Float getCarbonMonoxide() { + return carbonMonoxide; + } + + public Float getLat() { + return lat; + } + + public Float getLon() { + return lon; + } + + public Long getAirValuesTimestamp() { + return airValuesTimestamp; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public void setSensorId(Integer sensorId) { + this.sensorId = sensorId; + } + + public void setSensorType(String sensorType) { + this.sensorType = sensorType; + } + + public void setUnit(String unit) { + this.unit = unit; + } + + public void setSensorStatus(Integer sensorStatus) { + this.sensorStatus = sensorStatus; + } + + public void setSensorTimestamp(Long sensorTimestamp) { + this.sensorTimestamp = sensorTimestamp; + } + + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + public void setHumidity(Float humidity) { + this.humidity = humidity; + } + + public void setPressure(Float pressure) { + this.pressure = pressure; + } + + public void setCarbonMonoxide(Float carbonMonoxide) { + this.carbonMonoxide = carbonMonoxide; + } + + public void setLat(Float lat) { + this.lat = lat; + } + + public void setLon(Float lon) { + this.lon = lon; + } + + public void setAirValuesTimestamp(Long airValuesTimestamp) { + this.airValuesTimestamp = airValuesTimestamp; + } + + @Override + public int hashCode() { + return Objects.hash(airValuesTimestamp, carbonMonoxide, deviceId, humidity, lat, lon, pressure, sensorId, + sensorStatus, sensorTimestamp, sensorType, temperature, unit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ViewLatestValues other = (ViewLatestValues) obj; + return Objects.equals(airValuesTimestamp, other.airValuesTimestamp) + && Objects.equals(carbonMonoxide, other.carbonMonoxide) && Objects.equals(deviceId, other.deviceId) + && Objects.equals(humidity, other.humidity) && Objects.equals(lat, other.lat) + && Objects.equals(lon, other.lon) && Objects.equals(pressure, other.pressure) + && Objects.equals(sensorId, other.sensorId) && Objects.equals(sensorStatus, other.sensorStatus) + && Objects.equals(sensorTimestamp, other.sensorTimestamp) + && Objects.equals(sensorType, other.sensorType) && Objects.equals(temperature, other.temperature) + && Objects.equals(unit, other.unit); + } + + @Override + public String toString() { + return "ViewLatestValues [deviceId=" + deviceId + ", sensorId=" + sensorId + ", sensorType=" + sensorType + + ", unit=" + unit + ", sensorStatus=" + sensorStatus + ", sensorTimestamp=" + sensorTimestamp + + ", temperature=" + temperature + ", humidity=" + humidity + ", pressure=" + pressure + + ", carbonMonoxide=" + carbonMonoxide + ", lat=" + lat + ", lon=" + lon + ", airValuesTimestamp=" + + airValuesTimestamp + "]"; + } + + + +} diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/DevicePollutionMap.java b/backend/src/main/java/net/miarma/contaminus/entities/ViewPollutionMap.java similarity index 69% rename from backend/src/main/java/net/miarma/contaminus/database/entities/DevicePollutionMap.java rename to backend/src/main/java/net/miarma/contaminus/entities/ViewPollutionMap.java index 3caeced..7facd2d 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/DevicePollutionMap.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/ViewPollutionMap.java @@ -1,90 +1,116 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("v_pollution_map") -public class DevicePollutionMap { - private String deviceId; - private String deviceName; - private Float lat; - private Float lon; - private Float carbonMonoxide; - private Long timestamp; - - public DevicePollutionMap() {} - - public DevicePollutionMap(Row row) { - this.deviceId = row.getString("deviceId"); - this.deviceName = row.getString("deviceName"); - this.lat = row.getFloat("lat"); - this.lon = row.getFloat("lon"); - this.carbonMonoxide = row.getFloat("carbonMonoxide"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public DevicePollutionMap(String deviceId, String deviceName, Float lat, Float lon, Float carbonMonoxide, - Long timestamp) { - super(); - this.deviceId = deviceId; - this.deviceName = deviceName; - this.lat = lat; - this.lon = lon; - this.carbonMonoxide = carbonMonoxide; - this.timestamp = timestamp; - } - - public String getDeviceId() { - return deviceId; - } - - public String getDeviceName() { - return deviceName; - } - - public Float getLat() { - return lat; - } - - public Float getLon() { - return lon; - } - - public Float getCarbonMonoxide() { - return carbonMonoxide; - } - - public Long getTimestamp() { - return timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(carbonMonoxide, deviceId, deviceName, lat, lon, timestamp); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DevicePollutionMap other = (DevicePollutionMap) obj; - return Objects.equals(carbonMonoxide, other.carbonMonoxide) && Objects.equals(deviceId, other.deviceId) - && Objects.equals(deviceName, other.deviceName) && Objects.equals(lat, other.lat) - && Objects.equals(lon, other.lon) && Objects.equals(timestamp, other.timestamp); - } - - @Override - public String toString() { - return "DevicePollutionMap [deviceId=" + deviceId + ", deviceName=" + deviceName + ", lat=" + lat + ", lon=" - + lon + ", carbonMonoxide=" + carbonMonoxide + ", timestamp=" + timestamp + "]"; - } - - +package net.miarma.contaminus.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.util.DateParser; + +@Table("v_pollution_map") +public class ViewPollutionMap { + private String deviceId; + private String deviceName; + private Float lat; + private Float lon; + private Float carbonMonoxide; + private Long timestamp; + + public ViewPollutionMap() {} + + public ViewPollutionMap(Row row) { + this.deviceId = row.getString("deviceId"); + this.deviceName = row.getString("deviceName"); + this.lat = row.getFloat("lat"); + this.lon = row.getFloat("lon"); + this.carbonMonoxide = row.getFloat("carbonMonoxide"); + this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); + } + + public ViewPollutionMap(String deviceId, String deviceName, Float lat, Float lon, Float carbonMonoxide, + Long timestamp) { + super(); + this.deviceId = deviceId; + this.deviceName = deviceName; + this.lat = lat; + this.lon = lon; + this.carbonMonoxide = carbonMonoxide; + this.timestamp = timestamp; + } + + public String getDeviceId() { + return deviceId; + } + + public String getDeviceName() { + return deviceName; + } + + public Float getLat() { + return lat; + } + + public Float getLon() { + return lon; + } + + public Float getCarbonMonoxide() { + return carbonMonoxide; + } + + public Long getTimestamp() { + return timestamp; + } + + + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public void setLat(Float lat) { + this.lat = lat; + } + + public void setLon(Float lon) { + this.lon = lon; + } + + public void setCarbonMonoxide(Float carbonMonoxide) { + this.carbonMonoxide = carbonMonoxide; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(carbonMonoxide, deviceId, deviceName, lat, lon, timestamp); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ViewPollutionMap other = (ViewPollutionMap) obj; + return Objects.equals(carbonMonoxide, other.carbonMonoxide) && Objects.equals(deviceId, other.deviceId) + && Objects.equals(deviceName, other.deviceName) && Objects.equals(lat, other.lat) + && Objects.equals(lon, other.lon) && Objects.equals(timestamp, other.timestamp); + } + + @Override + public String toString() { + return "DevicePollutionMap [deviceId=" + deviceId + ", deviceName=" + deviceName + ", lat=" + lat + ", lon=" + + lon + ", carbonMonoxide=" + carbonMonoxide + ", timestamp=" + timestamp + "]"; + } + + } \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceSensorHistory.java b/backend/src/main/java/net/miarma/contaminus/entities/ViewSensorHistory.java similarity index 68% rename from backend/src/main/java/net/miarma/contaminus/database/entities/DeviceSensorHistory.java rename to backend/src/main/java/net/miarma/contaminus/entities/ViewSensorHistory.java index 2cd3bd8..04d5daa 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceSensorHistory.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/ViewSensorHistory.java @@ -1,82 +1,104 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("v_sensor_history_by_device") -public class DeviceSensorHistory { - private String deviceId; - private String deviceName; - private Float value; - private String valueType; - private Long timestamp; - - public DeviceSensorHistory() {} - - public DeviceSensorHistory(Row row) { - this.deviceId = row.getString("deviceId"); - this.deviceName = row.getString("deviceName"); - this.value = row.getFloat("value"); - this.valueType = row.getString("valueType"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public DeviceSensorHistory(String deviceId, String deviceName, Float value, String valueType, Long timestamp) { - super(); - this.deviceId = deviceId; - this.deviceName = deviceName; - this.value = value; - this.valueType = valueType; - this.timestamp = timestamp; - } - - public String getDeviceId() { - return deviceId; - } - - public String getDeviceName() { - return deviceName; - } - - public Float getValue() { - return value; - } - - public String getValueType() { - return valueType; - } - - public Long getTimestamp() { - return timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(deviceId, deviceName, timestamp, value, valueType); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DeviceSensorHistory other = (DeviceSensorHistory) obj; - return Objects.equals(deviceId, other.deviceId) && Objects.equals(deviceName, other.deviceName) - && Objects.equals(timestamp, other.timestamp) && Objects.equals(value, other.value) - && Objects.equals(valueType, other.valueType); - } - - @Override - public String toString() { - return "DeviceSensorHistory [deviceId=" + deviceId + ", deviceName=" + deviceName + ", value=" + value - + ", valueType=" + valueType + ", timestamp=" + timestamp + "]"; - } - - -} +package net.miarma.contaminus.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.util.DateParser; + +@Table("v_sensor_history_by_device") +public class ViewSensorHistory { + private String deviceId; + private String deviceName; + private Float value; + private String valueType; + private Long timestamp; + + public ViewSensorHistory() {} + + public ViewSensorHistory(Row row) { + this.deviceId = row.getString("deviceId"); + this.deviceName = row.getString("deviceName"); + this.value = row.getFloat("value"); + this.valueType = row.getString("valueType"); + this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); + } + + public ViewSensorHistory(String deviceId, String deviceName, Float value, String valueType, Long timestamp) { + super(); + this.deviceId = deviceId; + this.deviceName = deviceName; + this.value = value; + this.valueType = valueType; + this.timestamp = timestamp; + } + + public String getDeviceId() { + return deviceId; + } + + public String getDeviceName() { + return deviceName; + } + + public Float getValue() { + return value; + } + + public String getValueType() { + return valueType; + } + + public Long getTimestamp() { + return timestamp; + } + + + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public void setValue(Float value) { + this.value = value; + } + + public void setValueType(String valueType) { + this.valueType = valueType; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(deviceId, deviceName, timestamp, value, valueType); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ViewSensorHistory other = (ViewSensorHistory) obj; + return Objects.equals(deviceId, other.deviceId) && Objects.equals(deviceName, other.deviceName) + && Objects.equals(timestamp, other.timestamp) && Objects.equals(value, other.value) + && Objects.equals(valueType, other.valueType); + } + + @Override + public String toString() { + return "DeviceSensorHistory [deviceId=" + deviceId + ", deviceName=" + deviceName + ", value=" + value + + ", valueType=" + valueType + ", timestamp=" + timestamp + "]"; + } + + +} diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceSensorValue.java b/backend/src/main/java/net/miarma/contaminus/entities/ViewSensorValue.java similarity index 52% rename from backend/src/main/java/net/miarma/contaminus/database/entities/DeviceSensorValue.java rename to backend/src/main/java/net/miarma/contaminus/entities/ViewSensorValue.java index 6ff90fa..249f28c 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/DeviceSensorValue.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/ViewSensorValue.java @@ -1,131 +1,189 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("v_sensor_values") -public class DeviceSensorValue { - private Integer sensorId; - private String deviceId; - private String sensorType; - private String unit; - private Integer sensorStatus; - private Float temperature; - private Float humidity; - private Float carbonMonoxide; - private Float lat; - private Float lon; - private Long timestamp; - - public DeviceSensorValue() {} - - public DeviceSensorValue(Row row) { - this.sensorId = row.getInteger("sensorId"); - this.deviceId = row.getString("deviceId"); - this.sensorType = row.getString("sensorType"); - this.unit = row.getString("unit"); - this.sensorStatus = row.getInteger("sensorStatus"); - this.temperature = row.getFloat("temperature"); - this.humidity = row.getFloat("humidity"); - this.carbonMonoxide = row.getFloat("carbonMonoxide"); - this.lat = row.getFloat("lat"); - this.lon = row.getFloat("lon"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public DeviceSensorValue(Integer sensorId, String deviceId, String sensorType, String unit, Integer sensorStatus, - Float temperature, Float humidity, Float carbonMonoxide, Float lat, Float lon, Long timestamp) { - super(); - this.sensorId = sensorId; - this.deviceId = deviceId; - this.sensorType = sensorType; - this.unit = unit; - this.sensorStatus = sensorStatus; - this.temperature = temperature; - this.humidity = humidity; - this.carbonMonoxide = carbonMonoxide; - this.lat = lat; - this.lon = lon; - this.timestamp = timestamp; - } - - public Integer getSensorId() { - return sensorId; - } - - public String getDeviceId() { - return deviceId; - } - - public String getSensorType() { - return sensorType; - } - - public String getUnit() { - return unit; - } - - public Integer getSensorStatus() { - return sensorStatus; - } - - public Float getTemperature() { - return temperature; - } - - public Float getHumidity() { - return humidity; - } - - public Float getCarbonMonoxide() { - return carbonMonoxide; - } - - public Float getLat() { - return lat; - } - - public Float getLon() { - return lon; - } - - public Long getTimestamp() { - return timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(carbonMonoxide, deviceId, humidity, lat, lon, sensorId, sensorStatus, sensorType, - temperature, timestamp, unit); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DeviceSensorValue other = (DeviceSensorValue) obj; - return Objects.equals(carbonMonoxide, other.carbonMonoxide) && Objects.equals(deviceId, other.deviceId) - && Objects.equals(humidity, other.humidity) && Objects.equals(lat, other.lat) - && Objects.equals(lon, other.lon) && Objects.equals(sensorId, other.sensorId) - && Objects.equals(sensorStatus, other.sensorStatus) && Objects.equals(sensorType, other.sensorType) - && Objects.equals(temperature, other.temperature) && Objects.equals(timestamp, other.timestamp) - && Objects.equals(unit, other.unit); - } - - @Override - public String toString() { - return "DeviceSensorValue [sensorId=" + sensorId + ", deviceId=" + deviceId + ", sensorType=" + sensorType - + ", unit=" + unit + ", sensorStatus=" + sensorStatus + ", temperature=" + temperature + ", humidity=" - + humidity + ", carbonMonoxide=" + carbonMonoxide + ", lat=" + lat + ", lon=" + lon + ", timestamp=" - + timestamp + "]"; - } - - -} +package net.miarma.contaminus.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.util.DateParser; + +@Table("v_sensor_values") +public class ViewSensorValue { + private Integer sensorId; + private String deviceId; + private String sensorType; + private String unit; + private Integer sensorStatus; + private Float temperature; + private Float humidity; + private Float pressure; + private Float carbonMonoxide; + private Float lat; + private Float lon; + private Long timestamp; + + public ViewSensorValue() {} + + public ViewSensorValue(Row row) { + this.sensorId = row.getInteger("sensorId"); + this.deviceId = row.getString("deviceId"); + this.sensorType = row.getString("sensorType"); + this.unit = row.getString("unit"); + this.sensorStatus = row.getInteger("sensorStatus"); + this.temperature = row.getFloat("temperature"); + this.humidity = row.getFloat("humidity"); + this.pressure = row.getFloat("pressure"); + this.carbonMonoxide = row.getFloat("carbonMonoxide"); + this.lat = row.getFloat("lat"); + this.lon = row.getFloat("lon"); + this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); + } + + public ViewSensorValue(Integer sensorId, String deviceId, String sensorType, String unit, Integer sensorStatus, + Float temperature, Float humidity, Float pressure, Float carbonMonoxide, Float lat, Float lon, Long timestamp) { + super(); + this.sensorId = sensorId; + this.deviceId = deviceId; + this.sensorType = sensorType; + this.unit = unit; + this.sensorStatus = sensorStatus; + this.temperature = temperature; + this.humidity = humidity; + this.pressure = pressure; + this.carbonMonoxide = carbonMonoxide; + this.lat = lat; + this.lon = lon; + this.timestamp = timestamp; + } + + public Integer getSensorId() { + return sensorId; + } + + public String getDeviceId() { + return deviceId; + } + + public String getSensorType() { + return sensorType; + } + + public String getUnit() { + return unit; + } + + public Integer getSensorStatus() { + return sensorStatus; + } + + public Float getTemperature() { + return temperature; + } + + public Float getHumidity() { + return humidity; + } + + public Float getPressure() { + return pressure; + } + + public Float getCarbonMonoxide() { + return carbonMonoxide; + } + + public Float getLat() { + return lat; + } + + public Float getLon() { + return lon; + } + + public Long getTimestamp() { + return timestamp; + } + + + + public void setSensorId(Integer sensorId) { + this.sensorId = sensorId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public void setSensorType(String sensorType) { + this.sensorType = sensorType; + } + + public void setUnit(String unit) { + this.unit = unit; + } + + public void setSensorStatus(Integer sensorStatus) { + this.sensorStatus = sensorStatus; + } + + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + public void setHumidity(Float humidity) { + this.humidity = humidity; + } + + public void setPressure(Float pressure) { + this.pressure = pressure; + } + + public void setCarbonMonoxide(Float carbonMonoxide) { + this.carbonMonoxide = carbonMonoxide; + } + + public void setLat(Float lat) { + this.lat = lat; + } + + public void setLon(Float lon) { + this.lon = lon; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(carbonMonoxide, deviceId, humidity, lat, lon, pressure, sensorId, sensorStatus, sensorType, + temperature, timestamp, unit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ViewSensorValue other = (ViewSensorValue) obj; + return Objects.equals(carbonMonoxide, other.carbonMonoxide) && Objects.equals(deviceId, other.deviceId) + && Objects.equals(humidity, other.humidity) && Objects.equals(lat, other.lat) + && Objects.equals(lon, other.lon) && Objects.equals(pressure, other.pressure) + && Objects.equals(sensorId, other.sensorId) && Objects.equals(sensorStatus, other.sensorStatus) + && Objects.equals(sensorType, other.sensorType) && Objects.equals(temperature, other.temperature) + && Objects.equals(timestamp, other.timestamp) && Objects.equals(unit, other.unit); + } + + @Override + public String toString() { + return "ViewSensorValue [sensorId=" + sensorId + ", deviceId=" + deviceId + ", sensorType=" + sensorType + + ", unit=" + unit + ", sensorStatus=" + sensorStatus + ", temperature=" + temperature + ", humidity=" + + humidity + ", pressure=" + pressure + ", carbonMonoxide=" + carbonMonoxide + ", lat=" + lat + ", lon=" + + lon + ", timestamp=" + timestamp + "]"; + } + + + +} diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/WeatherValue.java b/backend/src/main/java/net/miarma/contaminus/entities/WeatherValue.java similarity index 95% rename from backend/src/main/java/net/miarma/contaminus/database/entities/WeatherValue.java rename to backend/src/main/java/net/miarma/contaminus/entities/WeatherValue.java index fe5e8ac..e521271 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/entities/WeatherValue.java +++ b/backend/src/main/java/net/miarma/contaminus/entities/WeatherValue.java @@ -1,131 +1,131 @@ -package net.miarma.contaminus.database.entities; - -import java.util.Objects; - -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Table; -import net.miarma.contaminus.util.DateParser; - -@Table("weather_values") -public class WeatherValue { - - private Integer valueId; - private String deviceId; - private Integer sensorId; - private Float temperature; - private Float humidity; - private Float pressure; - private Long timestamp; - - public WeatherValue() {} - - public WeatherValue(Row row) { - this.valueId = row.getInteger("valueId"); - this.deviceId = row.getString("deviceId"); - this.sensorId = row.getInteger("sensorId"); - this.temperature = row.getFloat("temperature"); - this.humidity = row.getFloat("humidity"); - this.pressure = row.getFloat("pressure"); - this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); - } - - public WeatherValue(Integer valueId, String deviceId, Integer sensorId, Float temperature, Float humidity, Float pressure, Long timestamp) { - super(); - this.valueId = valueId; - this.deviceId = deviceId; - this.sensorId = sensorId; - this.temperature = temperature; - this.humidity = humidity; - this.pressure = pressure; - this.timestamp = timestamp; - } - - public Integer getValueId() { - return valueId; - } - - public void setValueId(Integer valueId) { - this.valueId = valueId; - } - +package net.miarma.contaminus.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; +import net.miarma.contaminus.util.DateParser; + +@Table("weather_values") +public class WeatherValue { + + private Integer valueId; + private String deviceId; + private Integer sensorId; + private Float temperature; + private Float humidity; + private Float pressure; + private Long timestamp; + + public WeatherValue() {} + + public WeatherValue(Row row) { + this.valueId = row.getInteger("valueId"); + this.deviceId = row.getString("deviceId"); + this.sensorId = row.getInteger("sensorId"); + this.temperature = row.getFloat("temperature"); + this.humidity = row.getFloat("humidity"); + this.pressure = row.getFloat("pressure"); + this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp")); + } + + public WeatherValue(Integer valueId, String deviceId, Integer sensorId, Float temperature, Float humidity, Float pressure, Long timestamp) { + super(); + this.valueId = valueId; + this.deviceId = deviceId; + this.sensorId = sensorId; + this.temperature = temperature; + this.humidity = humidity; + this.pressure = pressure; + this.timestamp = timestamp; + } + + public Integer getValueId() { + return valueId; + } + + public void setValueId(Integer valueId) { + this.valueId = valueId; + } + public String getDeviceId() { return deviceId; - } - + } + public void setDeviceId(String deviceId) { this.deviceId = deviceId; - } - - public Integer getSensorId() { - return sensorId; - } - - public void setSensorId(Integer sensorId) { - this.sensorId = sensorId; - } - - public Float getTemperature() { - return temperature; - } - - public void setTemperature(Float temperature) { - this.temperature = temperature; - } - - public Float getHumidity() { - return humidity; - } - - public void setHumidity(Float humidity) { - this.humidity = humidity; - } - + } + + public Integer getSensorId() { + return sensorId; + } + + public void setSensorId(Integer sensorId) { + this.sensorId = sensorId; + } + + public Float getTemperature() { + return temperature; + } + + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + public Float getHumidity() { + return humidity; + } + + public void setHumidity(Float humidity) { + this.humidity = humidity; + } + public Float getPressure() { return pressure; - } - + } + public void setPressure(Float pressure) { this.pressure = pressure; - } - - public Long getTimestamp() { - return timestamp; - } - - public void setTimestamp(Long timestamp) { - this.timestamp = timestamp; - } - - @Override - public int hashCode() { - return Objects.hash(deviceId, humidity, pressure, sensorId, temperature, timestamp, valueId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - WeatherValue other = (WeatherValue) obj; - return Objects.equals(deviceId, other.deviceId) && Objects.equals(humidity, other.humidity) - && Objects.equals(pressure, other.pressure) && Objects.equals(sensorId, other.sensorId) - && Objects.equals(temperature, other.temperature) && Objects.equals(timestamp, other.timestamp) - && Objects.equals(valueId, other.valueId); - } - - @Override - public String toString() { - return "WeatherValue [valueId=" + valueId + ", deviceId=" + deviceId + ", sensorId=" + sensorId - + ", temperature=" + temperature + ", humidity=" + humidity + ", pressure=" + pressure + ", timestamp=" - + timestamp + "]"; - } - + } + + public Long getTimestamp() { + return timestamp; + } + + public void setTimestamp(Long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(deviceId, humidity, pressure, sensorId, temperature, timestamp, valueId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + WeatherValue other = (WeatherValue) obj; + return Objects.equals(deviceId, other.deviceId) && Objects.equals(humidity, other.humidity) + && Objects.equals(pressure, other.pressure) && Objects.equals(sensorId, other.sensorId) + && Objects.equals(temperature, other.temperature) && Objects.equals(timestamp, other.timestamp) + && Objects.equals(valueId, other.valueId); + } + + @Override + public String toString() { + return "WeatherValue [valueId=" + valueId + ", deviceId=" + deviceId + ", sensorId=" + sensorId + + ", temperature=" + temperature + ", humidity=" + humidity + ", pressure=" + pressure + ", timestamp=" + + timestamp + "]"; + } + public static WeatherValue fromPayload(DevicePayload payload) { return new WeatherValue(null, payload.getDeviceId(), payload.getSensorId(), payload.getTemperature(), payload.getHumidity(), payload.getPressure(), payload.getTimestamp()); - } - + } + } \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/server/DataLayerAPIVerticle.java b/backend/src/main/java/net/miarma/contaminus/server/DataLayerAPIVerticle.java deleted file mode 100644 index 1e8e3b8..0000000 --- a/backend/src/main/java/net/miarma/contaminus/server/DataLayerAPIVerticle.java +++ /dev/null @@ -1,529 +0,0 @@ -package net.miarma.contaminus.server; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import io.vertx.core.AbstractVerticle; -import io.vertx.core.Promise; -import io.vertx.core.Vertx; -import io.vertx.core.http.HttpMethod; -import io.vertx.core.json.JsonObject; -import io.vertx.ext.web.Router; -import io.vertx.ext.web.RoutingContext; -import io.vertx.ext.web.handler.BodyHandler; -import io.vertx.ext.web.handler.CorsHandler; -import io.vertx.jdbcclient.JDBCPool; -import net.miarma.contaminus.common.ConfigManager; -import net.miarma.contaminus.common.Constants; -import net.miarma.contaminus.common.SingleJsonResponse; -import net.miarma.contaminus.database.DatabaseManager; -import net.miarma.contaminus.database.QueryBuilder; -import net.miarma.contaminus.database.entities.Actuator; -import net.miarma.contaminus.database.entities.COValue; -import net.miarma.contaminus.database.entities.Device; -import net.miarma.contaminus.database.entities.DeviceLatestValuesView; -import net.miarma.contaminus.database.entities.DevicePayload; -import net.miarma.contaminus.database.entities.DevicePollutionMap; -import net.miarma.contaminus.database.entities.DeviceSensorHistory; -import net.miarma.contaminus.database.entities.DeviceSensorValue; -import net.miarma.contaminus.database.entities.GpsValue; -import net.miarma.contaminus.database.entities.Group; -import net.miarma.contaminus.database.entities.Sensor; -import net.miarma.contaminus.database.entities.WeatherValue; - -/* - * This class is a Verticle that will handle the Data Layer API. - */ - -@SuppressWarnings("unused") -public class DataLayerAPIVerticle extends AbstractVerticle { - private JDBCPool pool; - private DatabaseManager dbManager; - private ConfigManager configManager; - private final Gson gson = new GsonBuilder().serializeNulls().create(); - - @SuppressWarnings("deprecation") - public DataLayerAPIVerticle() { - this.configManager = ConfigManager.getInstance(); - String jdbcUrl = configManager.getJdbcUrl(); - String dbUser = configManager.getStringProperty("db.user"); - String dbPwd = configManager.getStringProperty("db.pwd"); - Integer poolSize = configManager.getIntProperty("db.poolSize"); - - JsonObject dbConfig = new JsonObject() - .put("url", jdbcUrl) - .put("user", dbUser) - .put("password", dbPwd) - .put("max_pool_size", poolSize != null ? poolSize : 10); - - this.pool = JDBCPool.pool(Vertx.vertx(), dbConfig); - } - - @Override - public void start(Promise startPromise) { - Constants.LOGGER.info("📡 Iniciando DataLayerAPIVerticle..."); - - dbManager = DatabaseManager.getInstance(pool); - - Router router = Router.router(vertx); - Set allowedMethods = new HashSet<>( - Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); // Por ejemplo - Set allowedHeaders = new HashSet<>(Arrays.asList("Content-Type", "Authorization")); - - router.route().handler(CorsHandler.create() - .allowCredentials(true) - .allowedHeaders(allowedHeaders) - .allowedMethods(allowedMethods)); - router.route().handler(BodyHandler.create()); - - // Payload - router.route(HttpMethod.POST, Constants.POST_PAYLOAD).handler(this::addDevicePayload); - - // Group Routes - router.route(HttpMethod.GET, Constants.GET_GROUPS).handler(this::getAllGroups); - router.route(HttpMethod.GET, Constants.GET_GROUP_BY_ID).handler(this::getGroupById); - router.route(HttpMethod.POST, Constants.POST_GROUPS).handler(this::addGroup); - router.route(HttpMethod.PUT, Constants.PUT_GROUP_BY_ID).handler(this::updateGroup); - - // Device Routes - router.route(HttpMethod.GET, Constants.GET_DEVICES).handler(this::getAllDevices); - router.route(HttpMethod.GET, Constants.GET_DEVICE_BY_ID).handler(this::getDeviceById); - router.route(HttpMethod.POST, Constants.POST_DEVICES).handler(this::addDevice); - router.route(HttpMethod.PUT, Constants.PUT_DEVICE_BY_ID).handler(this::updateDevice); - - // Sensor Routes - router.route(HttpMethod.GET, Constants.GET_SENSORS).handler(this::getAllSensors); - router.route(HttpMethod.GET, Constants.GET_SENSOR_BY_ID).handler(this::getSensorById); - router.route(HttpMethod.POST, Constants.POST_SENSORS).handler(this::addSensor); - router.route(HttpMethod.PUT, Constants.PUT_SENSOR_BY_ID).handler(this::updateSensor); - - // Actuator Routes - router.route(HttpMethod.GET, Constants.GET_ACTUATORS).handler(this::getAllActuators); - router.route(HttpMethod.GET, Constants.GET_ACTUATOR_BY_ID).handler(this::getActuatorById); - router.route(HttpMethod.POST, Constants.POST_ACTUATORS).handler(this::addActuator); - router.route(HttpMethod.PUT, Constants.PUT_ACTUATOR_BY_ID).handler(this::updateActuator); - - // Views Routes - router.route(HttpMethod.GET, Constants.GET_LATEST_VALUES_VIEW).handler(this::getLatestValuesView); - router.route(HttpMethod.GET, Constants.GET_POLLUTION_MAP_VIEW).handler(this::getDevicePollutionMapView); - router.route(HttpMethod.GET, Constants.GET_SENSOR_VALUES_VIEW).handler(this::getSensorValuesView); - router.route(HttpMethod.GET, Constants.GET_SENSOR_HISTORY_BY_DEVICE_VIEW).handler(this::getSensorHistoryByDeviceView); - - vertx.createHttpServer() - .requestHandler(router) - .listen(configManager.getDataApiPort(), configManager.getHost()); - - pool.query("SELECT 1").execute(ar -> { - if (ar.succeeded()) { - Constants.LOGGER.info("🟢 Connected to DB"); - startPromise.complete(); - } else { - Constants.LOGGER.error("🔴 Failed to connect to DB: " + ar.cause()); - startPromise.fail(ar.cause()); - } - }); - } - - private void addDevicePayload(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - DevicePayload devicePayload = gson.fromJson(body.toString(), DevicePayload.class); - COValue coValue = COValue.fromPayload(devicePayload); - GpsValue gpsValue = GpsValue.fromPayload(devicePayload); - WeatherValue weatherValue = WeatherValue.fromPayload(devicePayload); - - String coQuery = QueryBuilder - .insert(coValue) - .build(); - - String gpsQuery = QueryBuilder - .insert(gpsValue) - .build(); - - String weatherQuery = QueryBuilder - .insert(weatherValue) - .build(); - - dbManager.execute(coQuery, COValue.class, - onSuccess -> { - dbManager.execute(gpsQuery, GpsValue.class, - onSuccess2 -> { - dbManager.execute(weatherQuery, WeatherValue.class, - onSuccess3 -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(SingleJsonResponse.of("Payload added successfully"))); - }, - onFailure3 -> { - context.fail(500, onFailure3); - }); - }, - onFailure2 -> { - context.fail(500, onFailure2); - }); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getAllGroups(RoutingContext context) { - String query = QueryBuilder - .select(Group.class) - .build(); - - dbManager.execute(query, Group.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getGroupById(RoutingContext context) { - Integer groupId = Integer.parseInt(context.request().getParam("groupId")); - Group group = new Group(groupId, null); - - String query = QueryBuilder - .select(group) - .build(); - - dbManager.execute(query, Group.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void addGroup(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - Group group = gson.fromJson(body.toString(), Group.class); - - String query = QueryBuilder - .insert(group) - .build(); - - dbManager.execute(query, Group.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(SingleJsonResponse.of("Group added successfully"))); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void updateGroup(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - Group group = gson.fromJson(body.toString(), Group.class); - - String query = QueryBuilder - .update(group) - .build(); - - dbManager.execute(query, Group.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(SingleJsonResponse.of("Group updated successfully"))); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getAllDevices(RoutingContext context) { - String query = QueryBuilder - .select(Device.class) - .build(); - - dbManager.execute(query, Device.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getDeviceById(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - Device device = new Device(deviceId, null, null); - - String query = QueryBuilder - .select(device) - .build(); - - dbManager.execute(query, Device.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void addDevice(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - Device device = gson.fromJson(body.toString(), Device.class); - - String query = QueryBuilder - .insert(device) - .build(); - - dbManager.execute(query, Device.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(SingleJsonResponse.of("Device added successfully"))); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void updateDevice(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - Device device = gson.fromJson(body.toString(), Device.class); - - String query = QueryBuilder - .update(device) - .build(); - - dbManager.execute(query, Device.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(SingleJsonResponse.of("Device updated successfully"))); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getAllSensors(RoutingContext context) { - String query = QueryBuilder - .select(Sensor.class) - .build(); - - dbManager.execute(query, Sensor.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getSensorById(RoutingContext context) { - Integer sensorId = Integer.parseInt(context.request().getParam("sensorId")); - Sensor sensor = new Sensor(sensorId, null, null, null, null, null); - - String query = QueryBuilder - .select(sensor) - .build(); - - dbManager.execute(query, Sensor.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void addSensor(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - Sensor sensor = gson.fromJson(body.toString(), Sensor.class); - - String query = QueryBuilder - .insert(sensor) - .build(); - - dbManager.execute(query, Sensor.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(SingleJsonResponse.of("Sensor added successfully"))); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void updateSensor(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - Sensor sensor = gson.fromJson(body.toString(), Sensor.class); - - String query = QueryBuilder - .update(sensor) - .build(); - - dbManager.execute(query, Sensor.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(SingleJsonResponse.of("Sensor updated successfully"))); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getAllActuators(RoutingContext context) { - String query = QueryBuilder - .select(Actuator.class) - .build(); - - dbManager.execute(query, Actuator.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getActuatorById(RoutingContext context) { - Integer actuatorId = Integer.parseInt(context.request().getParam("actuatorId")); - Actuator actuator = new Actuator(actuatorId, null, null, null); - - String query = QueryBuilder - .select(actuator) - .build(); - - dbManager.execute(query, Actuator.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void addActuator(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - Actuator actuator = gson.fromJson(body.toString(), Actuator.class); - - String query = QueryBuilder - .insert(actuator) - .build(); - - dbManager.execute(query, Actuator.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(SingleJsonResponse.of("Actuator added successfully"))); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void updateActuator(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - Actuator actuator = gson.fromJson(body.toString(), Actuator.class); - - String query = QueryBuilder - .update(actuator) - .build(); - - dbManager.execute(query, Actuator.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(SingleJsonResponse.of("Actuator updated successfully"))); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getLatestValuesView(RoutingContext context) { - String query = QueryBuilder - .select(DeviceLatestValuesView.class) - .build(); - - dbManager.execute(query, DeviceLatestValuesView.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getDevicePollutionMapView(RoutingContext context) { - String query = QueryBuilder - .select(DevicePollutionMap.class) - .build(); - - dbManager.execute(query, DevicePollutionMap.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getSensorValuesView(RoutingContext context) { - String query = QueryBuilder - .select(DeviceSensorValue.class) - .build(); - - dbManager.execute(query, DeviceSensorValue.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - - private void getSensorHistoryByDeviceView(RoutingContext context) { - String query = QueryBuilder - .select(DeviceSensorHistory.class) - .build(); - - dbManager.execute(query, DeviceSensorHistory.class, - onSuccess -> { - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(onSuccess)); - }, - onFailure -> { - context.fail(500, onFailure); - }); - } - -} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/server/LogicLayerAPIVerticle.java b/backend/src/main/java/net/miarma/contaminus/server/LogicLayerAPIVerticle.java deleted file mode 100644 index 40566bc..0000000 --- a/backend/src/main/java/net/miarma/contaminus/server/LogicLayerAPIVerticle.java +++ /dev/null @@ -1,225 +0,0 @@ -package net.miarma.contaminus.server; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Stream; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import io.vertx.core.AbstractVerticle; -import io.vertx.core.Promise; -import io.vertx.core.Vertx; -import io.vertx.core.http.HttpMethod; -import io.vertx.ext.web.Router; -import io.vertx.ext.web.RoutingContext; -import io.vertx.ext.web.client.WebClient; -import io.vertx.ext.web.client.WebClientOptions; -import io.vertx.ext.web.handler.BodyHandler; -import io.vertx.ext.web.handler.CorsHandler; -import net.miarma.contaminus.common.ConfigManager; -import net.miarma.contaminus.common.Constants; -import net.miarma.contaminus.database.entities.Actuator; -import net.miarma.contaminus.database.entities.Device; -import net.miarma.contaminus.database.entities.DeviceLatestValuesView; -import net.miarma.contaminus.database.entities.DevicePollutionMap; -import net.miarma.contaminus.database.entities.DeviceSensorHistory; -import net.miarma.contaminus.database.entities.DeviceSensorValue; -import net.miarma.contaminus.database.entities.Sensor; -import net.miarma.contaminus.util.RestClientUtil; - -public class LogicLayerAPIVerticle extends AbstractVerticle { - private ConfigManager configManager; - private final Gson gson = new GsonBuilder().serializeNulls().create(); - private RestClientUtil restClient; - - public LogicLayerAPIVerticle() { - this.configManager = ConfigManager.getInstance(); - WebClientOptions options = new WebClientOptions() - .setUserAgent("ContaminUS"); - this.restClient = new RestClientUtil(WebClient.create(Vertx.vertx(), options)); - } - - @Override - public void start(Promise startPromise) { - Constants.LOGGER.info("📡 Iniciando LogicApiVerticle..."); - - Router router = Router.router(vertx); - Set allowedMethods = new HashSet<>( - Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); // Por ejemplo - Set allowedHeaders = new HashSet<>(Arrays.asList("Content-Type", "Authorization")); - - router.route().handler(CorsHandler.create() - .allowCredentials(true) - .allowedHeaders(allowedHeaders) - .allowedMethods(allowedMethods)); - - router.route().handler(BodyHandler.create()); - - router.route(HttpMethod.GET, Constants.GET_GROUP_DEVICES).handler(this::getGroupDevices); - router.route(HttpMethod.GET, Constants.GET_DEVICE_SENSORS).handler(this::getDeviceSensors); - router.route(HttpMethod.GET, Constants.GET_DEVICE_ACTUATORS).handler(this::getDeviceActuators); - router.route(HttpMethod.GET, Constants.GET_DEVICE_LATEST_VALUES).handler(this::getDeviceLatestValues); - router.route(HttpMethod.GET, Constants.GET_DEVICE_POLLUTION_MAP).handler(this::getDevicePollutionMap); - router.route(HttpMethod.GET, Constants.GET_DEVICE_HISTORY).handler(this::getDeviceHistory); - router.route(HttpMethod.GET, Constants.GET_SENSOR_VALUES).handler(this::getSensorValues); - - vertx.createHttpServer() - .requestHandler(router) - .listen(configManager.getLogicApiPort(), configManager.getHost()); - - startPromise.complete(); - } - - private void getGroupDevices(RoutingContext context) { - Integer groupId = Integer.parseInt(context.request().getParam("groupId")); - - Promise resultList = Promise.promise(); - resultList.future().onComplete(complete -> { - if(complete.succeeded()) { - List aux = Stream.of(complete.result()) - .filter(d -> d.getGroupId() == groupId) - .toList(); - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(aux)); - } else { - context.fail(500, complete.cause()); - } - }); - - this.restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), - Constants.GET_DEVICES, Device[].class, resultList); - } - - private void getDeviceSensors(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - Promise resultList = Promise.promise(); - resultList.future().onComplete(result -> { - if (result.succeeded()) { - Sensor[] sensors = result.result(); - List aux = Arrays.stream(sensors) - .filter(s -> s.getDeviceId() == deviceId) - .toList(); - context.response().putHeader("Content-Type", "application/json").end(gson.toJson(aux)); - } else { - context.response().setStatusCode(500).end(result.cause().getMessage()); - } - }); - - restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), - Constants.GET_SENSORS, Sensor[].class, resultList); - } - - private void getDeviceActuators(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - Promise resultList = Promise.promise(); - resultList.future().onComplete(result -> { - if (result.succeeded()) { - Actuator[] devices = result.result(); - List aux = Arrays.stream(devices) - .filter(a -> a.getDeviceId() == deviceId) - .toList(); - context.response().putHeader("Content-Type", "application/json").end(gson.toJson(aux)); - } else { - context.response().setStatusCode(500).end(result.cause().getMessage()); - } - }); - - restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), - Constants.GET_ACTUATORS, Actuator[].class, resultList); - } - - private void getDeviceLatestValues(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - - Promise resultList = Promise.promise(); - resultList.future().onComplete(complete -> { - if (complete.succeeded()) { - List aux = Stream.of(complete.result()) - .filter(elem -> elem.getDeviceId() == deviceId) - .toList(); - - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(aux)); - } else { - context.fail(500, complete.cause()); - } - }); - - this.restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), - Constants.GET_LATEST_VALUES_VIEW, DeviceLatestValuesView[].class, resultList); - } - - private void getDevicePollutionMap(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - - Promise resultList = Promise.promise(); - - resultList.future().onComplete(complete -> { - if (complete.succeeded()) { - List aux = Arrays.asList(complete.result()).stream() - .filter(elem -> elem.getDeviceId() == deviceId) - .toList(); - - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(aux)); - } else { - context.fail(500, complete.cause()); - } - }); - - this.restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), - Constants.GET_POLLUTION_MAP_VIEW, DevicePollutionMap[].class, resultList); - } - - private void getDeviceHistory(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - - Promise resultList = Promise.promise(); - - resultList.future().onComplete(complete -> { - if (complete.succeeded()) { - List aux = Arrays.asList(complete.result()).stream() - .filter(elem -> elem.getDeviceId() == deviceId) - .toList(); - - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(aux)); - } else { - context.fail(500, complete.cause()); - } - }); - - this.restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), - Constants.GET_SENSOR_HISTORY_BY_DEVICE_VIEW, DeviceSensorHistory[].class, resultList); - } - - private void getSensorValues(RoutingContext context) { - Integer sensorId = Integer.parseInt(context.request().getParam("sensorId")); - - Promise resultList = Promise.promise(); - - resultList.future().onComplete(complete -> { - if (complete.succeeded()) { - List aux = Arrays.asList(complete.result()).stream() - .filter(val -> val.getSensorId() == sensorId) - .toList(); - - context.response() - .putHeader("content-type", "application/json; charset=utf-8") - .end(gson.toJson(aux)); - } else { - context.fail(500, complete.cause()); - } - }); - - this.restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), - Constants.GET_SENSOR_VALUES_VIEW, DeviceSensorValue[].class, resultList); - } -} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/verticles/DataLayerAPIVerticle.java b/backend/src/main/java/net/miarma/contaminus/verticles/DataLayerAPIVerticle.java new file mode 100644 index 0000000..d488fa9 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/verticles/DataLayerAPIVerticle.java @@ -0,0 +1,479 @@ +package net.miarma.contaminus.verticles; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.BodyHandler; +import io.vertx.ext.web.handler.CorsHandler; +import io.vertx.sqlclient.Pool; +import net.miarma.contaminus.common.ConfigManager; +import net.miarma.contaminus.common.Constants; +import net.miarma.contaminus.common.SingleJsonResponse; +import net.miarma.contaminus.dao.ActuatorDAO; +import net.miarma.contaminus.dao.COValueDAO; +import net.miarma.contaminus.dao.DeviceDAO; +import net.miarma.contaminus.dao.GpsValueDAO; +import net.miarma.contaminus.dao.GroupDAO; +import net.miarma.contaminus.dao.SensorDAO; +import net.miarma.contaminus.dao.WeatherValueDAO; +import net.miarma.contaminus.dao.views.ViewLatestValuesDAO; +import net.miarma.contaminus.dao.views.ViewPollutionMapDAO; +import net.miarma.contaminus.dao.views.ViewSensorHistoryDAO; +import net.miarma.contaminus.dao.views.ViewSensorValueDAO; +import net.miarma.contaminus.db.DatabaseManager; +import net.miarma.contaminus.db.DatabaseProvider; +import net.miarma.contaminus.db.QueryBuilder; +import net.miarma.contaminus.entities.Actuator; +import net.miarma.contaminus.entities.Device; +import net.miarma.contaminus.entities.Group; +import net.miarma.contaminus.entities.Sensor; +import net.miarma.contaminus.entities.ViewLatestValues; +import net.miarma.contaminus.entities.ViewPollutionMap; +import net.miarma.contaminus.entities.ViewSensorHistory; +import net.miarma.contaminus.entities.ViewSensorValue; + + +/* + * This class is a Verticle that will handle the Data Layer API. + */ + +@SuppressWarnings("unused") +public class DataLayerAPIVerticle extends AbstractVerticle { + private DatabaseManager dbManager; + private ConfigManager configManager; + private final Gson gson = new GsonBuilder().serializeNulls().create(); + private Pool pool; + + private GroupDAO groupDAO; + private DeviceDAO deviceDAO; + private SensorDAO sensorDAO; + private ActuatorDAO actuatorDAO; + private COValueDAO coValueDAO; + private WeatherValueDAO weatherValueDAO; + private GpsValueDAO gpsValueDAO; + private ViewLatestValuesDAO viewLatestValuesDAO; + private ViewPollutionMapDAO viewPollutionMapDAO; + private ViewSensorHistoryDAO viewSensorHistoryDAO; + private ViewSensorValueDAO viewSensorValueDAO; + + public DataLayerAPIVerticle() { + this.configManager = ConfigManager.getInstance(); + } + + @Override + public void start(Promise startPromise) { + Constants.LOGGER.info("📡 Iniciando DataLayerAPIVerticle..."); + + this.pool = DatabaseProvider.createPool(vertx, configManager); + this.dbManager = DatabaseManager.getInstance(pool); + + this.groupDAO = new GroupDAO(pool); + this.deviceDAO = new DeviceDAO(pool); + this.sensorDAO = new SensorDAO(pool); + this.actuatorDAO = new ActuatorDAO(pool); + this.coValueDAO = new COValueDAO(pool); + this.weatherValueDAO = new WeatherValueDAO(pool); + this.gpsValueDAO = new GpsValueDAO(pool); + this.viewLatestValuesDAO = new ViewLatestValuesDAO(pool); + this.viewPollutionMapDAO = new ViewPollutionMapDAO(pool); + this.viewSensorHistoryDAO = new ViewSensorHistoryDAO(pool); + this.viewSensorValueDAO = new ViewSensorValueDAO(pool); + + Router router = Router.router(vertx); + Set allowedMethods = new HashSet<>( + Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); // Por ejemplo + Set allowedHeaders = new HashSet<>(Arrays.asList("Content-Type", "Authorization")); + + router.route().handler(CorsHandler.create() + .allowCredentials(true) + .allowedHeaders(allowedHeaders) + .allowedMethods(allowedMethods)); + router.route().handler(BodyHandler.create()); + + // Group Routes + router.route(HttpMethod.GET, Constants.GROUPS).handler(this::getAllGroups); + router.route(HttpMethod.GET, Constants.GROUP).handler(this::getGroupById); + router.route(HttpMethod.POST, Constants.GROUPS).handler(this::addGroup); + router.route(HttpMethod.PUT, Constants.GROUP).handler(this::updateGroup); + + // Device Routes + router.route(HttpMethod.GET, Constants.DEVICES).handler(this::getAllDevices); + router.route(HttpMethod.GET, Constants.DEVICE).handler(this::getDeviceById); + router.route(HttpMethod.POST, Constants.DEVICES).handler(this::addDevice); + router.route(HttpMethod.PUT, Constants.DEVICE).handler(this::updateDevice); + + // Sensor Routes + router.route(HttpMethod.GET, Constants.SENSORS).handler(this::getAllSensors); + router.route(HttpMethod.GET, Constants.SENSOR).handler(this::getSensorById); + router.route(HttpMethod.POST, Constants.SENSORS).handler(this::addSensor); + router.route(HttpMethod.PUT, Constants.SENSOR).handler(this::updateSensor); + + // Actuator Routes + router.route(HttpMethod.GET, Constants.ACTUATORS).handler(this::getAllActuators); + router.route(HttpMethod.GET, Constants.ACTUATOR).handler(this::getActuatorById); + router.route(HttpMethod.POST, Constants.ACTUATORS).handler(this::addActuator); + router.route(HttpMethod.PUT, Constants.ACTUATOR).handler(this::updateActuator); + + // Views Routes + router.route(HttpMethod.GET, Constants.VIEW_LATEST_VALUES).handler(this::getLatestValuesView); + router.route(HttpMethod.GET, Constants.VIEW_POLLUTION_MAP).handler(this::getDevicePollutionMapView); + router.route(HttpMethod.GET, Constants.VIEW_SENSOR_VALUES).handler(this::getSensorValuesView); + router.route(HttpMethod.GET, Constants.VIEW_SENSOR_HISTORY).handler(this::getSensorHistoryByDeviceView); + + vertx.createHttpServer() + .requestHandler(router) + .listen(configManager.getDataApiPort(), configManager.getHost()); + + pool.query("SELECT 1").execute(ar -> { + if (ar.succeeded()) { + Constants.LOGGER.info("🟢 Connected to DB"); + startPromise.complete(); + } else { + Constants.LOGGER.error("🔴 Failed to connect to DB: " + ar.cause()); + startPromise.fail(ar.cause()); + } + }); + } + + private void getAllGroups(RoutingContext context) { + groupDAO.getAll() + .onSuccess(groups -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(groups)); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void getGroupById(RoutingContext context) { + Integer groupId = Integer.parseInt(context.request().getParam("groupId")); + + groupDAO.getById(groupId) + .onSuccess(group -> { + if (group != null) { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(group)); + } else { + context.response().setStatusCode(404).end(); + } + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void addGroup(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + Group group = gson.fromJson(body.toString(), Group.class); + + groupDAO.insert(group) + .onSuccess(result -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(SingleJsonResponse.of("Group added successfully"))); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void updateGroup(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + Group group = gson.fromJson(body.toString(), Group.class); + + groupDAO.update(group) + .onSuccess(result -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(SingleJsonResponse.of("Group updated successfully"))); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void getAllDevices(RoutingContext context) { + Integer groupId = Integer.parseInt(context.request().getParam("groupId")); + + deviceDAO.getAllByGroupId(groupId) + .onSuccess(devices -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(devices)); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void getDeviceById(RoutingContext context) { + Integer groupId = Integer.parseInt(context.request().getParam("groupId")); + String deviceId = context.request().getParam("deviceId"); + + deviceDAO.getByIdAndGroupId(deviceId, groupId) + .onSuccess(device -> { + if (device != null) { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(device)); + } else { + context.response().setStatusCode(404).end(); + } + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void addDevice(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + Device device = gson.fromJson(body.toString(), Device.class); + + deviceDAO.insert(device) + .onSuccess(result -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(SingleJsonResponse.of("Device added successfully"))); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void updateDevice(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + Device device = gson.fromJson(body.toString(), Device.class); + + deviceDAO.update(device) + .onSuccess(result -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(SingleJsonResponse.of("Device updated successfully"))); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void getAllSensors(RoutingContext context) { + Integer groupId = Integer.parseInt(context.request().getParam("groupId")); + String deviceId = context.request().getParam("deviceId"); + + deviceDAO.getByIdAndGroupId(deviceId, groupId).compose(device -> { + if (device == null) { + return Future.succeededFuture(List.of()); + } + return sensorDAO.getAllByDeviceId(device.getDeviceId()); + }).onSuccess(sensors -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(sensors)); + }).onFailure(err -> { + context.response().setStatusCode(500).end("Error: " + err.getMessage()); + }); + } + + private void getSensorById(RoutingContext context) { + Integer sensorId = Integer.parseInt(context.request().getParam("sensorId")); + String deviceId = context.request().getParam("deviceId"); + Integer groupId = Integer.parseInt(context.request().getParam("groupId")); + + deviceDAO.getByIdAndGroupId(deviceId, groupId).compose(device -> { + if (device == null) { + return Future.succeededFuture(null); + } + return sensorDAO.getByIdAndDeviceId(sensorId, device.getDeviceId()); + }).onSuccess(sensor -> { + if (sensor == null) { + context.response().setStatusCode(404).end("Sensor no encontrado"); + return; + } + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(sensor)); + }).onFailure(err -> { + context.response().setStatusCode(500).end("Error: " + err.getMessage()); + }); + } + + private void addSensor(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + Sensor sensor = gson.fromJson(body.toString(), Sensor.class); + + sensorDAO.insert(sensor) + .onSuccess(result -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(SingleJsonResponse.of("Sensor added successfully"))); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void updateSensor(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + Sensor sensor = gson.fromJson(body.toString(), Sensor.class); + + sensorDAO.update(sensor) + .onSuccess(result -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(SingleJsonResponse.of("Sensor updated successfully"))); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void getAllActuators(RoutingContext context) { + Integer groupId = Integer.parseInt(context.request().getParam("groupId")); + String deviceId = context.request().getParam("deviceId"); + + deviceDAO.getByIdAndGroupId(deviceId, groupId).compose(device -> { + if (device == null) { + return Future.succeededFuture(List.of()); + } + return actuatorDAO.getAllByDeviceId(device.getDeviceId()); + }).onSuccess(actuators -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(actuators)); + }).onFailure(err -> { + context.response().setStatusCode(500).end("Error: " + err.getMessage()); + }); + } + + private void getActuatorById(RoutingContext context) { + Integer groupId = Integer.parseInt(context.request().getParam("groupId")); + String deviceId = context.request().getParam("deviceId"); + Integer actuatorId = Integer.parseInt(context.request().getParam("actuatorId")); + + deviceDAO.getByIdAndGroupId(deviceId, groupId).compose(device -> { + if (device == null) { + return Future.succeededFuture(null); + } + return actuatorDAO.getByIdAndDeviceId(actuatorId, device.getDeviceId()); + }).onSuccess(actuator -> { + if (actuator == null) { + context.response().setStatusCode(404).end("Actuator no encontrado"); + return; + } + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(actuator)); + }).onFailure(err -> { + context.response().setStatusCode(500).end("Error: " + err.getMessage()); + }); + } + + private void addActuator(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + Actuator actuator = gson.fromJson(body.toString(), Actuator.class); + + actuatorDAO.insert(actuator) + .onSuccess(result -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(SingleJsonResponse.of("Actuator added successfully"))); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void updateActuator(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + Actuator actuator = gson.fromJson(body.toString(), Actuator.class); + + actuatorDAO.update(actuator) + .onSuccess(result -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(SingleJsonResponse.of("Actuator updated successfully"))); + }) + .onFailure(err -> { + context.fail(500, err); + }); + } + + private void getLatestValuesView(RoutingContext context) { + String query = QueryBuilder + .select(ViewLatestValues.class) + .build(); + + dbManager.execute(query, ViewLatestValues.class, + onSuccess -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(onSuccess)); + }, + onFailure -> { + context.fail(500, onFailure); + }); + } + + private void getDevicePollutionMapView(RoutingContext context) { + String query = QueryBuilder + .select(ViewPollutionMap.class) + .build(); + + dbManager.execute(query, ViewPollutionMap.class, + onSuccess -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(onSuccess)); + }, + onFailure -> { + context.fail(500, onFailure); + }); + } + + private void getSensorValuesView(RoutingContext context) { + String query = QueryBuilder + .select(ViewSensorValue.class) + .build(); + + dbManager.execute(query, ViewSensorValue.class, + onSuccess -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(onSuccess)); + }, + onFailure -> { + context.fail(500, onFailure); + }); + } + + private void getSensorHistoryByDeviceView(RoutingContext context) { + String query = QueryBuilder + .select(ViewSensorHistory.class) + .build(); + + dbManager.execute(query, ViewSensorHistory.class, + onSuccess -> { + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(onSuccess)); + }, + onFailure -> { + context.fail(500, onFailure); + }); + } + +} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/verticles/LogicLayerAPIVerticle.java b/backend/src/main/java/net/miarma/contaminus/verticles/LogicLayerAPIVerticle.java new file mode 100644 index 0000000..f1f3215 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/verticles/LogicLayerAPIVerticle.java @@ -0,0 +1,160 @@ +package net.miarma.contaminus.verticles; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Promise; +import io.vertx.core.Vertx; +import io.vertx.core.http.HttpMethod; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientOptions; +import io.vertx.ext.web.handler.BodyHandler; +import io.vertx.ext.web.handler.CorsHandler; +import net.miarma.contaminus.common.ConfigManager; +import net.miarma.contaminus.common.Constants; +import net.miarma.contaminus.entities.ViewLatestValues; +import net.miarma.contaminus.entities.ViewPollutionMap; +import net.miarma.contaminus.entities.ViewSensorHistory; +import net.miarma.contaminus.entities.ViewSensorValue; +import net.miarma.contaminus.util.RestClientUtil; + +public class LogicLayerAPIVerticle extends AbstractVerticle { + private ConfigManager configManager; + private final Gson gson = new GsonBuilder().serializeNulls().create(); + private RestClientUtil restClient; + + public LogicLayerAPIVerticle() { + this.configManager = ConfigManager.getInstance(); + WebClientOptions options = new WebClientOptions() + .setUserAgent("ContaminUS"); + this.restClient = new RestClientUtil(WebClient.create(Vertx.vertx(), options)); + } + + @Override + public void start(Promise startPromise) { + Constants.LOGGER.info("📡 Iniciando LogicApiVerticle..."); + + Router router = Router.router(vertx); + Set allowedMethods = new HashSet<>( + Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); + Set allowedHeaders = new HashSet<>(Arrays.asList("Content-Type", "Authorization")); + + router.route().handler(CorsHandler.create() + .allowCredentials(true) + .allowedHeaders(allowedHeaders) + .allowedMethods(allowedMethods)); + + router.route().handler(BodyHandler.create()); + + router.route(HttpMethod.GET, Constants.LATEST_VALUES).handler(this::getDeviceLatestValues); + router.route(HttpMethod.GET, Constants.POLLUTION_MAP).handler(this::getDevicePollutionMap); + router.route(HttpMethod.GET, Constants.HISTORY).handler(this::getDeviceHistory); + router.route(HttpMethod.GET, Constants.SENSOR_VALUES).handler(this::getSensorValues); + + vertx.createHttpServer() + .requestHandler(router) + .listen(configManager.getLogicApiPort(), configManager.getHost()); + + startPromise.complete(); + } + + private void getDeviceLatestValues(RoutingContext context) { + String deviceId = context.request().getParam("deviceId"); + + Promise resultList = Promise.promise(); + resultList.future().onComplete(complete -> { + if (complete.succeeded()) { + List aux = Stream.of(complete.result()) + .filter(elem -> deviceId.equals(elem.getDeviceId())) + .toList(); + + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(aux)); + } else { + context.fail(500, complete.cause()); + } + }); + + this.restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), + Constants.VIEW_LATEST_VALUES, ViewLatestValues[].class, resultList); + } + + private void getDevicePollutionMap(RoutingContext context) { + String deviceId = context.request().getParam("deviceId"); + + Promise resultList = Promise.promise(); + + resultList.future().onComplete(complete -> { + if (complete.succeeded()) { + List aux = Arrays.asList(complete.result()).stream() + .filter(elem -> deviceId.equals(elem.getDeviceId())) + .toList(); + + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(aux)); + } else { + context.fail(500, complete.cause()); + } + }); + + this.restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), + Constants.VIEW_POLLUTION_MAP, ViewPollutionMap[].class, resultList); + } + + private void getDeviceHistory(RoutingContext context) { + String deviceId = context.request().getParam("deviceId"); + + Promise resultList = Promise.promise(); + + resultList.future().onComplete(complete -> { + if (complete.succeeded()) { + List aux = Arrays.asList(complete.result()).stream() + .filter(elem -> deviceId.equals(elem.getDeviceId())) + .toList(); + + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(aux)); + } else { + context.fail(500, complete.cause()); + } + }); + + this.restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), + Constants.VIEW_SENSOR_HISTORY, ViewSensorHistory[].class, resultList); + } + + private void getSensorValues(RoutingContext context) { + Integer sensorId = Integer.parseInt(context.request().getParam("sensorId")); + + Promise resultList = Promise.promise(); + + resultList.future().onComplete(complete -> { + if (complete.succeeded()) { + List aux = Arrays.asList(complete.result()).stream() + .filter(val -> val.getSensorId() == sensorId) + .toList(); + + context.response() + .putHeader("content-type", "application/json; charset=utf-8") + .end(gson.toJson(aux)); + } else { + context.fail(500, complete.cause()); + } + }); + + this.restClient.getRequest(configManager.getDataApiPort(), "http://" + configManager.getHost(), + Constants.VIEW_SENSOR_VALUES, ViewSensorValue[].class, resultList); + } +} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/server/MainVerticle.java b/backend/src/main/java/net/miarma/contaminus/verticles/MainVerticle.java similarity index 96% rename from backend/src/main/java/net/miarma/contaminus/server/MainVerticle.java rename to backend/src/main/java/net/miarma/contaminus/verticles/MainVerticle.java index 4ffe5a8..2ee8f9b 100644 --- a/backend/src/main/java/net/miarma/contaminus/server/MainVerticle.java +++ b/backend/src/main/java/net/miarma/contaminus/verticles/MainVerticle.java @@ -1,97 +1,96 @@ -package net.miarma.contaminus.server; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; - -import io.vertx.core.AbstractVerticle; -import io.vertx.core.DeploymentOptions; -import io.vertx.core.Launcher; -import io.vertx.core.Promise; -import io.vertx.core.ThreadingModel; -import net.miarma.contaminus.common.ConfigManager; -import net.miarma.contaminus.common.Constants; - -public class MainVerticle extends AbstractVerticle { - private ConfigManager configManager; - - public static void main(String[] args) { - Launcher.executeCommand("run", MainVerticle.class.getName()); - } - - private void init() { - this.configManager = ConfigManager.getInstance(); - initializeDirectories(); - copyDefaultConfig(); - } - - private void initializeDirectories() { - File baseDir = new File(this.configManager.getBaseDir()); - if (!baseDir.exists()) { - baseDir.mkdirs(); - } - } - - private void copyDefaultConfig() { - File configFile = new File(configManager.getConfigFile().getAbsolutePath()); - if (!configFile.exists()) { - try (InputStream in = MainVerticle.class.getClassLoader().getResourceAsStream("default.properties")) { - if (in != null) { - Files.copy(in, configFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } else { - Constants.LOGGER.error("🔴 Default config file not found in resources"); - } - } catch (IOException e) { - Constants.LOGGER.error("🔴 Failed to copy default config file", e); - } - } - } - - @Override - public void start(Promise startPromise) { - try { - System.setProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager"); - init(); - deployVerticles(startPromise); - } catch (Exception e) { - Constants.LOGGER.error("🔴 Error starting the application: " + e); - startPromise.fail(e); - } - } - - private void deployVerticles(Promise startPromise) { - final DeploymentOptions options = new DeploymentOptions(); - options.setThreadingModel(ThreadingModel.WORKER); - - vertx.deployVerticle(new DataLayerAPIVerticle(), options, result -> { - if (result.succeeded()) { - Constants.LOGGER.info("🟢 DatabaseVerticle desplegado"); - Constants.LOGGER.info("\t🔗 API URL: " + configManager.getHost() - + ":" + configManager.getDataApiPort()); - } else { - Constants.LOGGER.error("🔴 Error deploying DataLayerAPIVerticle: " + result.cause()); - } - }); - - vertx.deployVerticle(new LogicLayerAPIVerticle(), options, result -> { - if (result.succeeded()) { - Constants.LOGGER.info("🟢 LogicLayerAPIVerticle desplegado"); - Constants.LOGGER.info("\t🔗 API URL: " + configManager.getHost() - + ":" + configManager.getLogicApiPort()); - } else { - Constants.LOGGER.error("🔴 Error deploying LogicLayerAPIVerticle: " + result.cause()); - } - }); - - startPromise.complete(); - } - - @Override - public void stop(Promise stopPromise) throws Exception { - getVertx().deploymentIDs() - .forEach(v -> getVertx().undeploy(v)); - } - -} +package net.miarma.contaminus.verticles; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.DeploymentOptions; +import io.vertx.core.Launcher; +import io.vertx.core.Promise; +import io.vertx.core.ThreadingModel; +import net.miarma.contaminus.common.ConfigManager; +import net.miarma.contaminus.common.Constants; + +public class MainVerticle extends AbstractVerticle { + private ConfigManager configManager; + + public static void main(String[] args) { + Launcher.executeCommand("run", MainVerticle.class.getName()); + } + + private void init() { + this.configManager = ConfigManager.getInstance(); + initializeDirectories(); + copyDefaultConfig(); + } + + private void initializeDirectories() { + File baseDir = new File(this.configManager.getBaseDir()); + if (!baseDir.exists()) { + baseDir.mkdirs(); + } + } + + private void copyDefaultConfig() { + File configFile = new File(configManager.getConfigFile().getAbsolutePath()); + if (!configFile.exists()) { + try (InputStream in = MainVerticle.class.getClassLoader().getResourceAsStream("default.properties")) { + if (in != null) { + Files.copy(in, configFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } else { + Constants.LOGGER.error("🔴 Default config file not found in resources"); + } + } catch (IOException e) { + Constants.LOGGER.error("🔴 Failed to copy default config file", e); + } + } + } + + @Override + public void start(Promise startPromise) { + try { + init(); + deployVerticles(startPromise); + } catch (Exception e) { + Constants.LOGGER.error("🔴 Error starting the application: " + e); + startPromise.fail(e); + } + } + + private void deployVerticles(Promise startPromise) { + final DeploymentOptions options = new DeploymentOptions(); + options.setThreadingModel(ThreadingModel.WORKER); + + vertx.deployVerticle(new DataLayerAPIVerticle(), options, result -> { + if (result.succeeded()) { + Constants.LOGGER.info("🟢 DatabaseVerticle desplegado"); + Constants.LOGGER.info("\t🔗 API URL: " + configManager.getHost() + + ":" + configManager.getDataApiPort()); + } else { + Constants.LOGGER.error("🔴 Error deploying DataLayerAPIVerticle: " + result.cause()); + } + }); + + vertx.deployVerticle(new LogicLayerAPIVerticle(), options, result -> { + if (result.succeeded()) { + Constants.LOGGER.info("🟢 LogicLayerAPIVerticle desplegado"); + Constants.LOGGER.info("\t🔗 API URL: " + configManager.getHost() + + ":" + configManager.getLogicApiPort()); + } else { + Constants.LOGGER.error("🔴 Error deploying LogicLayerAPIVerticle: " + result.cause()); + } + }); + + startPromise.complete(); + } + + @Override + public void stop(Promise stopPromise) throws Exception { + getVertx().deploymentIDs() + .forEach(v -> getVertx().undeploy(v)); + } + +} diff --git a/backend/src/main/java/net/miarma/contaminus/server/MqttVerticle.java b/backend/src/main/java/net/miarma/contaminus/verticles/MqttVerticle.java similarity index 81% rename from backend/src/main/java/net/miarma/contaminus/server/MqttVerticle.java rename to backend/src/main/java/net/miarma/contaminus/verticles/MqttVerticle.java index b79b3b6..e26df3d 100644 --- a/backend/src/main/java/net/miarma/contaminus/server/MqttVerticle.java +++ b/backend/src/main/java/net/miarma/contaminus/verticles/MqttVerticle.java @@ -1,18 +1,18 @@ -package net.miarma.contaminus.server; - -import io.vertx.core.AbstractVerticle; -import io.vertx.core.Promise; - -public class MqttVerticle extends AbstractVerticle { - - @Override - public void start(Promise startPromise) { - - } - - @Override - public void stop(Promise startPromise) { - - } - -} +package net.miarma.contaminus.verticles; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Promise; + +public class MqttVerticle extends AbstractVerticle { + + @Override + public void start(Promise startPromise) { + + } + + @Override + public void stop(Promise startPromise) { + + } + +} diff --git a/backend/src/main/resources/default.properties b/backend/src/main/resources/default.properties index e0824ae..5cb15b1 100644 --- a/backend/src/main/resources/default.properties +++ b/backend/src/main/resources/default.properties @@ -1,14 +1,14 @@ -# DB Configuration -db.protocol=jdbc:mariadb -db.host=localhost -db.port=3306 -db.name=dad -db.user=root -db.pwd=root -dp.poolSize=5 - -# HTTP Server Configuration -inet.host=localhost -webserver.port=8080 -data-api.port=8081 +# DB Configuration +db.protocol=jdbc:mariadb +db.host=localhost +db.port=3306 +db.name=dad +db.user=root +db.password=root +dp.poolSize=5 + +# HTTP Server Configuration +inet.host=localhost +webserver.port=8080 +data-api.port=8081 logic-api.port=8082 \ No newline at end of file diff --git a/backend/src/main/resources/logback.xml b/backend/src/main/resources/logback.xml new file mode 100644 index 0000000..13de8fc --- /dev/null +++ b/backend/src/main/resources/logback.xml @@ -0,0 +1,20 @@ + + + + + + %cyan([%d{HH:mm:ss}]) %highlight(%-5level) %green(%logger{20}) - %msg%n + + + + + + + + + + + + + + diff --git a/frontend/src/components/SummaryCards.jsx b/frontend/src/components/SummaryCards.jsx index 61a6a45..427e8a7 100644 --- a/frontend/src/components/SummaryCards.jsx +++ b/frontend/src/components/SummaryCards.jsx @@ -1,77 +1,77 @@ -import PropTypes from 'prop-types'; -import CardContainer from './CardContainer'; - -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faCloud, faClock, faTemperature0, faWater } from '@fortawesome/free-solid-svg-icons'; - -import { DataProvider } from '@/context/DataContext'; -import { useDataContext } from '@/hooks/useDataContext'; - -import { useConfig } from '@/hooks/useConfig.js'; -import { DateParser } from '@/util/dateParser'; - -const SummaryCards = ({ deviceId }) => { - const { config, configLoading, configError } = useConfig(); - - if (configLoading) return

Cargando configuración...

; - if (configError) return

Error al cargar configuración: {configError}

; - if (!config) return

Configuración no disponible.

; - - const BASE = config.appConfig.endpoints.LOGIC_URL; - const ENDPOINT = config.appConfig.endpoints.GET_DEVICE_LATEST_VALUES; - const endp = ENDPOINT.replace('{0}', deviceId); - - const reqConfig = { - baseUrl: `${BASE}${endp}`, - params: {} - } - - return ( - - - - ); -} - -const SummaryCardsContent = () => { - const { data, dataLoading, dataError } = useDataContext(); - - if (dataLoading) return

Cargando datos...

; - if (dataError) return

Error al cargar datos: {dataError}

; - if (!data) return

Datos no disponibles.

; - - const CardsData = [ - { id: 1, title: "Temperatura", content: "N/A", status: "Esperando datos...", titleIcon: }, - { id: 2, title: "Humedad", content: "N/A", status: "Esperando datos...", titleIcon: }, - { id: 3, title: "Nivel de CO", content: "N/A", status: "Esperando datos...", titleIcon: }, - { id: 4, title: "Actualizado a las", content: "N/A", status: "Esperando datos...", titleIcon: } - ]; - - if (data) { - let coData = data[1]; - let tempData = data[2]; - - let lastTime = DateParser.timestampToString(coData.airValuesTimestamp); - let lastDate = new Date(coData.airValuesTimestamp); - - CardsData[0].content = tempData.temperature + "°C"; - CardsData[0].status = "Temperatura actual"; - CardsData[1].content = tempData.humidity + "%"; - CardsData[1].status = "Humedad actual"; - CardsData[2].content = coData.carbonMonoxide + " ppm"; - CardsData[2].status = "Nivel de CO actual"; - CardsData[3].content = lastTime; - CardsData[3].status = "Día " + lastDate.toLocaleDateString(); - - } - - return ( - - ); -} - -SummaryCards.propTypes = { - deviceId: PropTypes.number.isRequired -}; - +import PropTypes from 'prop-types'; +import CardContainer from './CardContainer'; + +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faCloud, faClock, faTemperature0, faWater } from '@fortawesome/free-solid-svg-icons'; + +import { DataProvider } from '@/context/DataContext'; +import { useDataContext } from '@/hooks/useDataContext'; + +import { useConfig } from '@/hooks/useConfig.js'; +import { DateParser } from '@/util/dateParser'; + +const SummaryCards = ({ deviceId }) => { + const { config, configLoading, configError } = useConfig(); + + if (configLoading) return

Cargando configuración...

; + if (configError) return

Error al cargar configuración: {configError}

; + if (!config) return

Configuración no disponible.

; + + const BASE = config.appConfig.endpoints.LOGIC_URL; + const ENDPOINT = config.appConfig.endpoints.GET_DEVICE_LATEST_VALUES; + const endp = ENDPOINT.replace('{0}', deviceId); + + const reqConfig = { + baseUrl: `${BASE}${endp}`, + params: {} + } + + return ( + + + + ); +} + +const SummaryCardsContent = () => { + const { data, dataLoading, dataError } = useDataContext(); + + if (dataLoading) return

Cargando datos...

; + if (dataError) return

Error al cargar datos: {dataError}

; + if (!data) return

Datos no disponibles.

; + + const CardsData = [ + { id: 1, title: "Temperatura", content: "N/A", status: "Esperando datos...", titleIcon: }, + { id: 2, title: "Humedad", content: "N/A", status: "Esperando datos...", titleIcon: }, + { id: 3, title: "Nivel de CO", content: "N/A", status: "Esperando datos...", titleIcon: }, + { id: 4, title: "Actualizado a las", content: "N/A", status: "Esperando datos...", titleIcon: } + ]; + + if (data) { + let coData = data[1]; + let tempData = data[2]; + + let lastTime = DateParser.timestampToString(coData.timestamp); + let lastDate = new Date(coData.timestamp); + + CardsData[0].content = tempData.temperature + "°C"; + CardsData[0].status = "Temperatura actual"; + CardsData[1].content = tempData.humidity + "%"; + CardsData[1].status = "Humedad actual"; + CardsData[2].content = coData.carbonMonoxide + " ppm"; + CardsData[2].status = "Nivel de CO actual"; + CardsData[3].content = lastTime; + CardsData[3].status = "Día " + lastDate.toLocaleDateString(); + + } + + return ( + + ); +} + +SummaryCards.propTypes = { + deviceId: PropTypes.number.isRequired +}; + export default SummaryCards; \ No newline at end of file diff --git a/hardware/include/JsonTools.hpp b/hardware/include/JsonTools.hpp index 826e550..61ff282 100644 --- a/hardware/include/JsonTools.hpp +++ b/hardware/include/JsonTools.hpp @@ -2,6 +2,9 @@ #include #include +#include "BME280.hpp" +#include "MQ7v2.hpp" +#include "GPS.hpp" String serializeSensorValue( int sensorId, @@ -12,15 +15,13 @@ String serializeSensorValue( const BME280Data_t &bme, const MQ7Data_t &mq7, const GPSData_t &gps, - long timestamp -); + long timestamp); String serializeActuatorStatus( int actuatorId, const String &deviceId, int status, - long timestamp -); + long timestamp); void deserializeSensorValue(HTTPClient &http, int httpResponseCode); void deserializeActuatorStatus(HTTPClient &http, int httpResponseCode); diff --git a/hardware/include/main.hpp b/hardware/include/main.hpp index 3bd9765..44b90d6 100644 --- a/hardware/include/main.hpp +++ b/hardware/include/main.hpp @@ -1,51 +1,51 @@ -#include - -#define SERVER_IP "https://contaminus.miarma.net/api/v1/" -#define REST_PORT 443 -#define MQTT_PORT 1883 - -#define MQ7_ID 1 -#define BME280_ID 2 -#define GPS_ID 3 -#define MAX7219_ID 1 - -#define DEBUG - -#include "JsonTools.hpp" -#include "RestClient.hpp" -#include "WifiConnection.hpp" -#include "MqttClient.hpp" -#include "BME280.hpp" -#include "GPS.hpp" -#include "MAX7219.hpp" -#include "MQ7v2.hpp" - -struct TaskTimer -{ - uint32_t lastRun = 0; - uint32_t interval = 1000; - - TaskTimer() = default; - - TaskTimer(uint32_t last, uint32_t interval) - : lastRun(last), interval(interval) {} -}; - -struct SensorInfo -{ - int id; - String type; -}; - -enum AirQualityStatus -{ - GOOD, - BAD -}; - -void readMQ7(); -void readBME280(); -void readGPS(); -void writeMatrix(const char* message); -void printAllData(); +#include + +#define SERVER_IP "https://contaminus.miarma.net/api/v1/" +#define REST_PORT 443 +#define MQTT_PORT 1883 + +#define MQ7_ID 1 +#define BME280_ID 2 +#define GPS_ID 3 +#define MAX7219_ID 1 + +#define DEBUG + +#include "JsonTools.hpp" +#include "RestClient.hpp" +#include "WifiConnection.hpp" +#include "MqttClient.hpp" +#include "BME280.hpp" +#include "GPS.hpp" +#include "MAX7219.hpp" +#include "MQ7v2.hpp" + +struct TaskTimer +{ + uint32_t lastRun = 0; + uint32_t interval = 1000; + + TaskTimer() = default; + + TaskTimer(uint32_t last, uint32_t interval) + : lastRun(last), interval(interval) {} +}; + +struct SensorInfo +{ + int id; + String type; +}; + +enum AirQualityStatus +{ + GOOD, + BAD +}; + +void readMQ7(); +void readBME280(); +void readGPS(); +void writeMatrix(const char *message); +void printAllData(); uint32_t getChipID(); \ No newline at end of file diff --git a/hardware/src/lib/http/JsonTools.cpp b/hardware/src/lib/http/JsonTools.cpp index 31fa9a2..20b4dcd 100644 --- a/hardware/src/lib/http/JsonTools.cpp +++ b/hardware/src/lib/http/JsonTools.cpp @@ -1,159 +1,179 @@ -#include "JsonTools.hpp" - -String serializeSensorValue( - int sensorId, - const String &deviceId, - const String &sensorType, - const String &unit, - int sensorStatus, - const BME280Data_t &bme, - const MQ7Data_t &mq7, - const GPSData_t &gps, - long timestamp -) { - DynamicJsonDocument doc(1024); - - doc["sensorId"] = sensorId; - doc["deviceId"] = deviceId; - doc["sensorType"] = sensorType; - doc["unit"] = unit; - doc["sensorStatus"] = sensorStatus; - doc["temperature"] = bme.temperature; - doc["humidity"] = bme.humidity; - doc["pressure"] = bme.pressure; - doc["carbonMonoxide"] = mq7.co; - doc["lat"] = gps.lat; - doc["lon"] = gps.lon; - doc["timestamp"] = timestamp; - - String output; - serializeJson(doc, output); - Serial.println(output); - return output; -} - -String serializeActuatorStatus(const int actuatorId, const String &deviceId, const int status, const long timestamp) { - DynamicJsonDocument doc(512); - - doc["actuatorId"] = actuatorId; - doc["deviceId"] = deviceId; - doc["status"] = status; - doc["timestamp"] = timestamp; - - String output; - serializeJson(doc, output); - Serial.println(output); - return output; -} - -String serializeDevice(const String &deviceId, int groupId, const String &deviceName) { - DynamicJsonDocument doc(512); - - doc["deviceId"] = deviceId; - doc["groupId"] = groupId; - doc["deviceName"] = deviceName; - - String output; - serializeJson(doc, output); - Serial.println(output); - return output; -} - -void deserializeSensorValue(HTTPClient &http, int httpResponseCode) { - if (httpResponseCode > 0) { - Serial.print("HTTP Response code: "); - Serial.println(httpResponseCode); - String responseJson = http.getString(); - DynamicJsonDocument doc(ESP.getMaxAllocHeap()); - DeserializationError error = deserializeJson(doc, responseJson); - - if (error) { - Serial.print(F("deserializeJson() failed: ")); - Serial.println(error.f_str()); - return; - } - - JsonArray array = doc.as(); - for (JsonObject sensor : array) { - int sensorId = sensor["sensorId"]; - String deviceId = sensor["deviceId"]; - String sensorType = sensor["sensorType"]; - String unit = sensor["unit"]; - int sensorStatus = sensor["sensorStatus"]; - float temperature = sensor["temperature"]; - float humidity = sensor["humidity"]; - float carbonMonoxide = sensor["carbonMonoxide"]; - float lat = sensor["lat"]; - float lon = sensor["lon"]; - long timestamp = sensor["timestamp"]; - - Serial.println("Sensor deserialized:"); - Serial.printf(" ID: %d\n Device: %s\n Type: %s\n Unit: %s\n Status: %d\n Temp: %.2f\n Hum: %.2f\n CO: %.2f\n Lat: %.6f\n Lon: %.6f\n Time: %ld\n\n", - sensorId, deviceId.c_str(), sensorType.c_str(), unit.c_str(), sensorStatus, - temperature, humidity, carbonMonoxide, lat, lon, timestamp); - } - } else { - Serial.print("Error code: "); - Serial.println(httpResponseCode); - } -} - -void deserializeActuatorStatus(HTTPClient &http, int httpResponseCode) { - if (httpResponseCode > 0) { - Serial.print("HTTP Response code: "); - Serial.println(httpResponseCode); - String responseJson = http.getString(); - DynamicJsonDocument doc(ESP.getMaxAllocHeap()); - DeserializationError error = deserializeJson(doc, responseJson); - - if (error) { - Serial.print(F("deserializeJson() failed: ")); - Serial.println(error.f_str()); - return; - } - - JsonArray array = doc.as(); - for (JsonObject actuator : array) { - int actuatorId = actuator["actuatorId"]; - String deviceId = actuator["deviceId"]; - int status = actuator["status"]; - long timestamp = actuator["timestamp"]; - - Serial.println("Actuator deserialized:"); - Serial.printf(" ID: %d\n Device: %s\n Status: %d\n Time: %ld\n\n", - actuatorId, deviceId.c_str(), status, timestamp); - } - } else { - Serial.print("Error code: "); - Serial.println(httpResponseCode); - } -} - -void deserializeDevice(HTTPClient &http, int httpResponseCode) { - if (httpResponseCode > 0) { - Serial.print("HTTP Response code: "); - Serial.println(httpResponseCode); - String responseJson = http.getString(); - DynamicJsonDocument doc(ESP.getMaxAllocHeap()); - DeserializationError error = deserializeJson(doc, responseJson); - - if (error) { - Serial.print(F("deserializeJson() failed: ")); - Serial.println(error.f_str()); - return; - } - - JsonArray array = doc.as(); - for (JsonObject device : array) { - String deviceId = device["deviceId"]; - int groupId = device["groupId"]; - String deviceName = device["deviceName"]; - - Serial.println("Device deserialized:"); - Serial.printf(" ID: %s\n Group: %d\n Name: %s\n\n", deviceId.c_str(), groupId, deviceName.c_str()); - } - } else { - Serial.print("Error code: "); - Serial.println(httpResponseCode); - } +#include "JsonTools.hpp" + +String serializeSensorValue( + int sensorId, + const String &deviceId, + const String &sensorType, + const String &unit, + int sensorStatus, + const BME280Data_t &bme, + const MQ7Data_t &mq7, + const GPSData_t &gps, + long timestamp) +{ + DynamicJsonDocument doc(1024); + + doc["sensorId"] = sensorId; + doc["deviceId"] = deviceId; + doc["sensorType"] = sensorType; + doc["unit"] = unit; + doc["sensorStatus"] = sensorStatus; + doc["temperature"] = bme.temperature; + doc["humidity"] = bme.humidity; + doc["pressure"] = bme.pressure; + doc["carbonMonoxide"] = mq7.co; + doc["lat"] = gps.lat; + doc["lon"] = gps.lon; + doc["timestamp"] = timestamp; + + String output; + serializeJson(doc, output); + Serial.println(output); + return output; +} + +String serializeActuatorStatus(const int actuatorId, const String &deviceId, const int status, const long timestamp) +{ + DynamicJsonDocument doc(512); + + doc["actuatorId"] = actuatorId; + doc["deviceId"] = deviceId; + doc["status"] = status; + doc["timestamp"] = timestamp; + + String output; + serializeJson(doc, output); + Serial.println(output); + return output; +} + +String serializeDevice(const String &deviceId, int groupId, const String &deviceName) +{ + DynamicJsonDocument doc(512); + + doc["deviceId"] = deviceId; + doc["groupId"] = groupId; + doc["deviceName"] = deviceName; + + String output; + serializeJson(doc, output); + Serial.println(output); + return output; +} + +void deserializeSensorValue(HTTPClient &http, int httpResponseCode) +{ + if (httpResponseCode > 0) + { + Serial.print("HTTP Response code: "); + Serial.println(httpResponseCode); + String responseJson = http.getString(); + DynamicJsonDocument doc(ESP.getMaxAllocHeap()); + DeserializationError error = deserializeJson(doc, responseJson); + + if (error) + { + Serial.print(F("deserializeJson() failed: ")); + Serial.println(error.f_str()); + return; + } + + JsonArray array = doc.as(); + for (JsonObject sensor : array) + { + int sensorId = sensor["sensorId"]; + String deviceId = sensor["deviceId"]; + String sensorType = sensor["sensorType"]; + String unit = sensor["unit"]; + int sensorStatus = sensor["sensorStatus"]; + float temperature = sensor["temperature"]; + float humidity = sensor["humidity"]; + float carbonMonoxide = sensor["carbonMonoxide"]; + float lat = sensor["lat"]; + float lon = sensor["lon"]; + long timestamp = sensor["timestamp"]; + + Serial.println("Sensor deserialized:"); + Serial.printf(" ID: %d\n Device: %s\n Type: %s\n Unit: %s\n Status: %d\n Temp: %.2f\n Hum: %.2f\n CO: %.2f\n Lat: %.6f\n Lon: %.6f\n Time: %ld\n\n", + sensorId, deviceId.c_str(), sensorType.c_str(), unit.c_str(), sensorStatus, + temperature, humidity, carbonMonoxide, lat, lon, timestamp); + } + } + else + { + Serial.print("Error code: "); + Serial.println(httpResponseCode); + } +} + +void deserializeActuatorStatus(HTTPClient &http, int httpResponseCode) +{ + if (httpResponseCode > 0) + { + Serial.print("HTTP Response code: "); + Serial.println(httpResponseCode); + String responseJson = http.getString(); + DynamicJsonDocument doc(ESP.getMaxAllocHeap()); + DeserializationError error = deserializeJson(doc, responseJson); + + if (error) + { + Serial.print(F("deserializeJson() failed: ")); + Serial.println(error.f_str()); + return; + } + + JsonArray array = doc.as(); + for (JsonObject actuator : array) + { + int actuatorId = actuator["actuatorId"]; + String deviceId = actuator["deviceId"]; + int status = actuator["status"]; + long timestamp = actuator["timestamp"]; + + Serial.println("Actuator deserialized:"); + Serial.printf(" ID: %d\n Device: %s\n Status: %d\n Time: %ld\n\n", + actuatorId, deviceId.c_str(), status, timestamp); + } + } + else + { + Serial.print("Error code: "); + Serial.println(httpResponseCode); + } +} + +void deserializeDevice(HTTPClient &http, int httpResponseCode) +{ + if (httpResponseCode > 0) + { + Serial.print("HTTP Response code: "); + Serial.println(httpResponseCode); + String responseJson = http.getString(); + DynamicJsonDocument doc(ESP.getMaxAllocHeap()); + DeserializationError error = deserializeJson(doc, responseJson); + + if (error) + { + Serial.print(F("deserializeJson() failed: ")); + Serial.println(error.f_str()); + return; + } + + JsonArray array = doc.as(); + for (JsonObject device : array) + { + String deviceId = device["deviceId"]; + int groupId = device["groupId"]; + String deviceName = device["deviceName"]; + + Serial.println("Device deserialized:"); + Serial.printf(" ID: %s\n Group: %d\n Name: %s\n\n", deviceId.c_str(), groupId, deviceName.c_str()); + } + } + else + { + Serial.print("Error code: "); + Serial.println(httpResponseCode); + } } \ No newline at end of file diff --git a/hardware/src/lib/http/RestClient.cpp b/hardware/src/lib/http/RestClient.cpp index 2ef4778..52c3229 100644 --- a/hardware/src/lib/http/RestClient.cpp +++ b/hardware/src/lib/http/RestClient.cpp @@ -1,28 +1,34 @@ -#include "RestClient.hpp" - -HTTPClient httpClient; // HTTP client object - -void getRequest(const String url, String &response) -{ - httpClient.begin(url); - int httpCode = httpClient.GET(); - if (httpCode > 0) { - response = httpClient.getString(); - } else { - response = "Error: " + String(httpCode); - } - httpClient.end(); -} - -void postRequest(const String url, String &payload, String &response) -{ - httpClient.begin(url); - httpClient.addHeader("Content-Type", "application/json"); - int httpCode = httpClient.POST(payload); - if (httpCode > 0) { - response = httpClient.getString(); - } else { - response = "Error: " + String(httpCode); - } - httpClient.end(); +#include "RestClient.hpp" + +HTTPClient httpClient; // HTTP client object + +void getRequest(const String url, String &response) +{ + httpClient.begin(url); + int httpCode = httpClient.GET(); + if (httpCode > 0) + { + response = httpClient.getString(); + } + else + { + response = "Error: " + String(httpCode); + } + httpClient.end(); +} + +void postRequest(const String url, String &payload, String &response) +{ + httpClient.begin(url); + httpClient.addHeader("Content-Type", "application/json"); + int httpCode = httpClient.POST(payload); + if (httpCode > 0) + { + response = httpClient.getString(); + } + else + { + response = "Error: " + String(httpCode); + } + httpClient.end(); } \ No newline at end of file diff --git a/hardware/src/lib/inet/MqttClient.cpp b/hardware/src/lib/inet/MqttClient.cpp index e4b2088..0bd19d9 100644 --- a/hardware/src/lib/inet/MqttClient.cpp +++ b/hardware/src/lib/inet/MqttClient.cpp @@ -1,61 +1,62 @@ -#include "MqttClient.hpp" - -// MQTT configuration -WiFiClient espClient; -PubSubClient client(espClient); - -void OnMqttReceived(char *topic, byte *payload, unsigned int length) -{ - Serial.print("Received on "); - Serial.print(topic); - Serial.print(": "); - - String content = ""; - - for (size_t i = 0; i < length; i++) { - content.concat((char)payload[i]); - } - - Serial.print(content); - Serial.println(); -} - -void InitMqtt(const char * MQTTServerAddress, uint16_t MQTTServerPort) -{ - client.setServer(MQTTServerAddress, MQTTServerPort); - client.setCallback(OnMqttReceived); -} - -// conecta o reconecta al MQTT -// consigue conectar -> suscribe a topic y publica un mensaje -// no -> espera 5 segundos -void ConnectMqtt(const char * MQTTClientName) -{ - Serial.print("Starting MQTT connection..."); - if (client.connect(MQTTClientName)) - { - client.subscribe("hello/world"); - client.publish("hello/world", "connected"); - } - else - { - Serial.print("Failed MQTT connection, rc="); - Serial.print(client.state()); - Serial.println(" try again in 5 seconds"); - - delay(5000); - } -} - -// gestiona la comunicación MQTT -// comprueba que el cliente está conectado -// no -> intenta reconectar -// si -> llama al MQTT loop -void HandleMqtt(const char * MQTTClientName) -{ - if (!client.connected()) - { - ConnectMqtt(MQTTClientName); - } - client.loop(); -} +#include "MqttClient.hpp" + +// MQTT configuration +WiFiClient espClient; +PubSubClient client(espClient); + +void OnMqttReceived(char *topic, byte *payload, unsigned int length) +{ + Serial.print("Received on "); + Serial.print(topic); + Serial.print(": "); + + String content = ""; + + for (size_t i = 0; i < length; i++) + { + content.concat((char)payload[i]); + } + + Serial.print(content); + Serial.println(); +} + +void InitMqtt(const char *MQTTServerAddress, uint16_t MQTTServerPort) +{ + client.setServer(MQTTServerAddress, MQTTServerPort); + client.setCallback(OnMqttReceived); +} + +// conecta o reconecta al MQTT +// consigue conectar -> suscribe a topic y publica un mensaje +// no -> espera 5 segundos +void ConnectMqtt(const char *MQTTClientName) +{ + Serial.print("Starting MQTT connection..."); + if (client.connect(MQTTClientName)) + { + client.subscribe("hello/world"); + client.publish("hello/world", "connected"); + } + else + { + Serial.print("Failed MQTT connection, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + + delay(5000); + } +} + +// gestiona la comunicación MQTT +// comprueba que el cliente está conectado +// no -> intenta reconectar +// si -> llama al MQTT loop +void HandleMqtt(const char *MQTTClientName) +{ + if (!client.connected()) + { + ConnectMqtt(MQTTClientName); + } + client.loop(); +} diff --git a/hardware/src/lib/inet/WifiConnection.cpp b/hardware/src/lib/inet/WifiConnection.cpp index ab65eb2..8927410 100644 --- a/hardware/src/lib/inet/WifiConnection.cpp +++ b/hardware/src/lib/inet/WifiConnection.cpp @@ -1,83 +1,86 @@ -#include - -#define PIN_R 12 -#define PIN_G 13 -#define PIN_B 14 - -WiFiClient wifiClient; - -void setColor(uint8_t r, uint8_t g, uint8_t b) { - ledcWrite(0, r); - ledcWrite(1, g); - ledcWrite(2, b); -} - -void setupLED() { - ledcAttachPin(PIN_R, 0); - ledcAttachPin(PIN_G, 1); - ledcAttachPin(PIN_B, 2); - - ledcSetup(0, 5000, 8); - ledcSetup(1, 5000, 8); - ledcSetup(2, 5000, 8); -} - -// hue cycle -void hueCycle(uint8_t pos) { - uint8_t r = (uint8_t)(sin((pos + 0) * 0.024) * 127 + 128); - uint8_t g = (uint8_t)(sin((pos + 85) * 0.024) * 127 + 128); - uint8_t b = (uint8_t)(sin((pos + 170) * 0.024) * 127 + 128); - setColor(r, g, b); -} - -int setupWifi() -{ - setupLED(); - - WiFi.mode(WIFI_STA); - WiFi.begin(SSID, PASSWORD); - - #ifdef DEBUG - Serial.print("Conectando a la red WiFi: "); - Serial.print(SSID); - #endif - - int hue = 0; - uint32_t start = millis(); - const uint32_t timeout = 15000; - - while (WiFi.status() != WL_CONNECTED && millis() - start < timeout) - { - hueCycle(hue++); - - #ifdef DEBUG - Serial.print("."); - #endif - - delay(30); - } - - if (WiFi.status() == WL_CONNECTED) - { - setColor(0, 255, 0); - - #ifdef DEBUG - Serial.println("Conectado a la red WiFi"); - Serial.print("Dirección IP: "); - Serial.println(WiFi.localIP()); - #endif - - return 0; - } - else - { - setColor(255, 0, 0); - - #ifdef DEBUG - Serial.println("No se pudo conectar a la red WiFi"); - #endif - - return 1; - } -} - +#include + +#define PIN_R 12 +#define PIN_G 13 +#define PIN_B 14 + +WiFiClient wifiClient; + +void setColor(uint8_t r, uint8_t g, uint8_t b) +{ + ledcWrite(0, r); + ledcWrite(1, g); + ledcWrite(2, b); +} + +void setupLED() +{ + ledcSetup(0, 5000, 8); + ledcAttachPin(PIN_R, 0); + + ledcSetup(1, 5000, 8); + ledcAttachPin(PIN_G, 1); + + ledcSetup(2, 5000, 8); + ledcAttachPin(PIN_B, 2); +} + +// hue cycle +void hueCycle(uint8_t pos) +{ + uint8_t r = (uint8_t)(sin((pos + 0) * 0.024) * 127 + 128); + uint8_t g = (uint8_t)(sin((pos + 85) * 0.024) * 127 + 128); + uint8_t b = (uint8_t)(sin((pos + 170) * 0.024) * 127 + 128); + setColor(r, g, b); +} + +int setupWifi() +{ + setupLED(); + + WiFi.mode(WIFI_STA); + WiFi.begin(SSID, PASSWORD); + +#ifdef DEBUG + Serial.print("Conectando a la red WiFi: "); + Serial.print(SSID); +#endif + + int hue = 0; + uint32_t start = millis(); + const uint32_t timeout = 15000; + + while (WiFi.status() != WL_CONNECTED && millis() - start < timeout) + { + hueCycle(hue++); + +#ifdef DEBUG + Serial.print("."); +#endif + + delay(30); + } + + if (WiFi.status() == WL_CONNECTED) + { + setColor(0, 255, 0); + +#ifdef DEBUG + Serial.println("Conectado a la red WiFi"); + Serial.print("Dirección IP: "); + Serial.println(WiFi.localIP()); +#endif + + return 0; + } + else + { + setColor(255, 0, 0); + +#ifdef DEBUG + Serial.println("No se pudo conectar a la red WiFi"); +#endif + + return 1; + } +} \ No newline at end of file diff --git a/hardware/src/lib/sensor/BME280.cpp b/hardware/src/lib/sensor/BME280.cpp index b129470..bde5a1c 100644 --- a/hardware/src/lib/sensor/BME280.cpp +++ b/hardware/src/lib/sensor/BME280.cpp @@ -1,34 +1,34 @@ -#include "BME280.hpp" - -BME280I2C bme; - -void BME280_Init() -{ - Wire.setPins(21, 22); - Wire.begin(); - - BME280I2C::Settings settings( - BME280I2C::OSR::OSR_X1, - BME280I2C::OSR::OSR_X1, - BME280I2C::OSR::OSR_X1, - BME280I2C::Mode::Mode_Forced, // modo forzado - BME280I2C::StandbyTime::StandbyTime_1000ms, - BME280I2C::Filter::Filter_16, - BME280I2C::SpiEnable::SpiEnable_False, - BME280I2C::I2CAddr::I2CAddr_0x76 // dirección I2C del BME280 - ); - - bme.setSettings(settings); - - while (!bme.begin()); -} - -BME280Data_t BME280_Read() -{ - float p, t, h; - BME280::TempUnit tUnit(BME280::TempUnit_Celsius); - BME280::PresUnit pUnit(BME280::PresUnit_Pa); - bme.read(p, t, h, tUnit, pUnit); - return {p, t, h}; -} - +#include "BME280.hpp" + +BME280I2C bme; + +void BME280_Init() +{ + Wire.setPins(21, 22); + Wire.begin(); + + BME280I2C::Settings settings( + BME280I2C::OSR::OSR_X1, + BME280I2C::OSR::OSR_X1, + BME280I2C::OSR::OSR_X1, + BME280I2C::Mode::Mode_Forced, // modo forzado + BME280I2C::StandbyTime::StandbyTime_1000ms, + BME280I2C::Filter::Filter_16, + BME280I2C::SpiEnable::SpiEnable_False, + BME280I2C::I2CAddr::I2CAddr_0x76 // dirección I2C del BME280 + ); + + bme.setSettings(settings); + + while (!bme.begin()) + ; +} + +BME280Data_t BME280_Read() +{ + float p, t, h; + BME280::TempUnit tUnit(BME280::TempUnit_Celsius); + BME280::PresUnit pUnit(BME280::PresUnit_Pa); + bme.read(p, t, h, tUnit, pUnit); + return {p, t, h}; +} diff --git a/hardware/src/main.cpp b/hardware/src/main.cpp index 789e287..2f99c34 100644 --- a/hardware/src/main.cpp +++ b/hardware/src/main.cpp @@ -3,7 +3,7 @@ const uint32_t DEVICE_ID = getChipID(); const char ALL_VEHICLES[] = "Todo tipo de vehiculos"; const char ELECTRIC_VEHICLES[] = "Solo vehiculos electricos/hibridos"; -const char* currentMessage = nullptr; +const char *currentMessage = nullptr; TaskTimer matrixTimer{0, 25}; TaskTimer globalTimer{0, 60000}; @@ -29,7 +29,7 @@ void setup() GPS_Init(); Serial.println("Sensor GPS inicializado"); MQ7_Init(); - Serial.println("Sensor MQ7 inicializado"); + Serial.println("Sensor MQ7 inicializado"); MAX7219_Init(); Serial.println("Display inicializado"); @@ -40,8 +40,10 @@ void loop() { uint32_t now = millis(); - if (now - matrixTimer.lastRun >= matrixTimer.interval) { - if (MAX7219_Animate()) { + if (now - matrixTimer.lastRun >= matrixTimer.interval) + { + if (MAX7219_Animate()) + { MAX7219_ResetAnimation(); } matrixTimer.lastRun = now; @@ -52,10 +54,10 @@ void loop() readBME280(); readGPS(); readMQ7(); - - #ifdef DEBUG + +#ifdef DEBUG printAllData(); - #endif +#endif globalTimer.lastRun = now; } @@ -69,11 +71,15 @@ void readMQ7() AirQualityStatus newStatus = (mq7Data.co >= CO_THRESHOLD) ? BAD : GOOD; - if (newStatus != currentAirStatus) { + if (newStatus != currentAirStatus) + { currentAirStatus = newStatus; - if (currentAirStatus == BAD) { + if (currentAirStatus == BAD) + { writeMatrix(ELECTRIC_VEHICLES); - } else { + } + else + { writeMatrix(ALL_VEHICLES); } } @@ -89,15 +95,16 @@ void readGPS() gpsData = GPS_Read(); } -void writeMatrix(const char* message) +void writeMatrix(const char *message) { - if (currentMessage == message) return; + if (currentMessage == message) + return; currentMessage = message; - #ifdef DEBUG +#ifdef DEBUG Serial.println("Escribiendo en el display..."); - #endif - +#endif + MAX7219_DisplayText(message, PA_LEFT, 50, 0); } @@ -105,17 +112,28 @@ void printAllData() { Serial.println("---------------------"); - Serial.print("ID: "); Serial.println(DEVICE_ID, HEX); + Serial.print("ID: "); + Serial.println(DEVICE_ID, HEX); - Serial.print("Presión: "); Serial.print(bme280Data.pressure / 100); Serial.println(" hPa"); - Serial.print("Temperatura: "); Serial.print(bme280Data.temperature); Serial.println(" °C"); - Serial.print("Humedad: "); Serial.print(bme280Data.humidity); Serial.println(" %"); + Serial.print("Presión: "); + Serial.print(bme280Data.pressure / 100); + Serial.println(" hPa"); + Serial.print("Temperatura: "); + Serial.print(bme280Data.temperature); + Serial.println(" °C"); + Serial.print("Humedad: "); + Serial.print(bme280Data.humidity); + Serial.println(" %"); - Serial.print("Latitud: "); Serial.println(gpsData.lat); - Serial.print("Longitud: "); Serial.println(gpsData.lon); + Serial.print("Latitud: "); + Serial.println(gpsData.lat); + Serial.print("Longitud: "); + Serial.println(gpsData.lon); - Serial.print("CO: "); Serial.println(mq7Data.co); - Serial.print("D0: "); Serial.println(mq7Data.threshold); + Serial.print("CO: "); + Serial.println(mq7Data.co); + Serial.print("D0: "); + Serial.println(mq7Data.threshold); } uint32_t getChipID() @@ -125,8 +143,9 @@ uint32_t getChipID() { chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; } - #ifdef DEBUG - Serial.print("Chip ID: "); Serial.println(chipId, HEX); - #endif +#ifdef DEBUG + Serial.print("Chip ID: "); + Serial.println(chipId, HEX); +#endif return chipId; }