added some improved classes from my custom backend and introduced DAOs
This commit is contained in:
@@ -18,6 +18,13 @@
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Vert.X MariaDB/MySQL Client -->
|
||||
<dependency>
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-mysql-client</artifactId>
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Vert.X Web -->
|
||||
<dependency>
|
||||
<groupId>io.vertx</groupId>
|
||||
@@ -46,13 +53,6 @@
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JDBC Driver -->
|
||||
<dependency>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
<artifactId>mariadb-java-client</artifactId>
|
||||
<version>3.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
@@ -60,11 +60,17 @@
|
||||
<version>2.12.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/io.quarkus/quarkus-agroal -->
|
||||
<!-- SLF4J + Logback -->
|
||||
<dependency>
|
||||
<groupId>org.jboss.logmanager</groupId>
|
||||
<artifactId>jboss-logmanager</artifactId>
|
||||
<version>3.1.1.Final</version> <!-- O la versión más reciente -->
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>2.0.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.5.13</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +1,40 @@
|
||||
package net.miarma.contaminus.common;
|
||||
|
||||
import io.vertx.core.impl.logging.Logger;
|
||||
import io.vertx.core.impl.logging.LoggerFactory;
|
||||
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 POST_PAYLOAD = RAW_API_PREFIX + "/device-payload";
|
||||
public static final String GROUPS = RAW_API_PREFIX + "/groups";
|
||||
public static final String GROUP = RAW_API_PREFIX + "/groups/:groupId";
|
||||
|
||||
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 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 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 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 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 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 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";
|
||||
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.");
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.miarma.contaminus.common;
|
||||
|
||||
public interface ValuableEnum {
|
||||
int getValue();
|
||||
}
|
||||
129
backend/src/main/java/net/miarma/contaminus/dao/ActuatorDAO.java
Normal file
129
backend/src/main/java/net/miarma/contaminus/dao/ActuatorDAO.java
Normal file
@@ -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<Actuator, Integer>{
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public ActuatorDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<Actuator>> getAll() {
|
||||
Promise<List<Actuator>> 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<List<Actuator>> getAllByDeviceId(String deviceId) {
|
||||
Promise<List<Actuator>> 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<Actuator> getById(Integer id) {
|
||||
Promise<Actuator> 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<Actuator> getByIdAndDeviceId(Integer actuatorId, String deviceId) {
|
||||
Promise<Actuator> 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<Actuator> insert(Actuator t) {
|
||||
Promise<Actuator> 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<Actuator> update(Actuator t) {
|
||||
Promise<Actuator> 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<Actuator> delete(Integer id) {
|
||||
Promise<Actuator> 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();
|
||||
}
|
||||
}
|
||||
@@ -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<COValue, Integer> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public COValueDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<COValue>> getAll() {
|
||||
Promise<List<COValue>> 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<COValue> getById(Integer id) {
|
||||
Promise<COValue> 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<COValue> insert(COValue t) {
|
||||
Promise<COValue> 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<COValue> update(COValue t) {
|
||||
Promise<COValue> 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<COValue> delete(Integer id) {
|
||||
throw new UnsupportedOperationException("Cannot delete samples");
|
||||
}
|
||||
|
||||
}
|
||||
128
backend/src/main/java/net/miarma/contaminus/dao/DeviceDAO.java
Normal file
128
backend/src/main/java/net/miarma/contaminus/dao/DeviceDAO.java
Normal file
@@ -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<Device, String> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public DeviceDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<Device>> getAll() {
|
||||
Promise<List<Device>> 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<List<Device>> getAllByGroupId(Integer groupId) {
|
||||
Promise<List<Device>> 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<Device> getById(String id) {
|
||||
Promise<Device> 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<Device> getByIdAndGroupId(String id, Integer groupId) {
|
||||
Promise<Device> 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<Device> insert(Device t) {
|
||||
Promise<Device> 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<Device> update(Device t) {
|
||||
Promise<Device> 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<Device> delete(String id) {
|
||||
Promise<Device> 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();
|
||||
}
|
||||
}
|
||||
@@ -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<GpsValue, Integer> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public GpsValueDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<GpsValue>> getAll() {
|
||||
Promise<List<GpsValue>> 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<GpsValue> getById(Integer id) {
|
||||
Promise<GpsValue> 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<GpsValue> insert(GpsValue t) {
|
||||
Promise<GpsValue> 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<GpsValue> update(GpsValue t) {
|
||||
Promise<GpsValue> 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<GpsValue> delete(Integer id) {
|
||||
throw new UnsupportedOperationException("Cannot delete samples");
|
||||
}
|
||||
}
|
||||
@@ -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<Group, Integer> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public GroupDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<Group>> getAll() {
|
||||
Promise<List<Group>> 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<Group> getById(Integer id) {
|
||||
Promise<Group> 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<Group> insert(Group t) {
|
||||
Promise<Group> 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<Group> update(Group t) {
|
||||
Promise<Group> 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<Group> delete(Integer id) {
|
||||
Promise<Group> 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();
|
||||
}
|
||||
|
||||
}
|
||||
130
backend/src/main/java/net/miarma/contaminus/dao/SensorDAO.java
Normal file
130
backend/src/main/java/net/miarma/contaminus/dao/SensorDAO.java
Normal file
@@ -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<Sensor, Integer> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public SensorDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<Sensor>> getAll() {
|
||||
Promise<List<Sensor>> 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<List<Sensor>> getAllByDeviceId(String deviceId) {
|
||||
Promise<List<Sensor>> 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<Sensor> getById(Integer id) {
|
||||
Promise<Sensor> 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<Sensor> getByIdAndDeviceId(Integer sensorId, String deviceId) {
|
||||
Promise<Sensor> 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<Sensor> insert(Sensor t) {
|
||||
Promise<Sensor> 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<Sensor> update(Sensor t) {
|
||||
Promise<Sensor> 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<Sensor> delete(Integer id) {
|
||||
Promise<Sensor> 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();
|
||||
}
|
||||
}
|
||||
@@ -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<WeatherValue, Integer> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public WeatherValueDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<WeatherValue>> getAll() {
|
||||
Promise<List<WeatherValue>> 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<WeatherValue> getById(Integer id) {
|
||||
Promise<WeatherValue> 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<WeatherValue> insert(WeatherValue t) {
|
||||
Promise<WeatherValue> 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<WeatherValue> update(WeatherValue t) {
|
||||
Promise<WeatherValue> 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<WeatherValue> delete(Integer id) {
|
||||
throw new UnsupportedOperationException("Cannot delete samples");
|
||||
}
|
||||
}
|
||||
@@ -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<ViewLatestValues, String> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public ViewLatestValuesDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<ViewLatestValues>> getAll() {
|
||||
Promise<List<ViewLatestValues>> 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<ViewLatestValues> getById(String id) {
|
||||
Promise<ViewLatestValues> 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<ViewLatestValues> insert(ViewLatestValues t) {
|
||||
throw new UnsupportedOperationException("Insert not supported for views");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ViewLatestValues> update(ViewLatestValues t) {
|
||||
throw new UnsupportedOperationException("Update not supported for views");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ViewLatestValues> delete(String id) {
|
||||
throw new UnsupportedOperationException("Delete not supported for views");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<ViewPollutionMap, String> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
public ViewPollutionMapDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<ViewPollutionMap>> getAll() {
|
||||
Promise<List<ViewPollutionMap>> 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<ViewPollutionMap> getById(String id) {
|
||||
Promise<ViewPollutionMap> 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<ViewPollutionMap> insert(ViewPollutionMap t) {
|
||||
throw new UnsupportedOperationException("Insert not supported for views");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ViewPollutionMap> update(ViewPollutionMap t) {
|
||||
throw new UnsupportedOperationException("Update not supported for views");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ViewPollutionMap> delete(String id) {
|
||||
throw new UnsupportedOperationException("Delete not supported for views");
|
||||
}
|
||||
}
|
||||
@@ -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<ViewSensorHistory, String> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public ViewSensorHistoryDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<ViewSensorHistory>> getAll() {
|
||||
Promise<List<ViewSensorHistory>> 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<ViewSensorHistory> getById(String id) {
|
||||
Promise<ViewSensorHistory> 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<ViewSensorHistory> insert(ViewSensorHistory t) {
|
||||
throw new UnsupportedOperationException("Insert not supported for views");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ViewSensorHistory> update(ViewSensorHistory t) {
|
||||
throw new UnsupportedOperationException("Update not supported for views");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ViewSensorHistory> delete(String id) {
|
||||
throw new UnsupportedOperationException("Delete not supported for views");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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<ViewSensorValue, Integer> {
|
||||
|
||||
private final DatabaseManager db;
|
||||
|
||||
public ViewSensorValueDAO(Pool pool) {
|
||||
this.db = DatabaseManager.getInstance(pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<List<ViewSensorValue>> getAll() {
|
||||
Promise<List<ViewSensorValue>> 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<ViewSensorValue> getById(Integer id) {
|
||||
Promise<ViewSensorValue> 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<ViewSensorValue> insert(ViewSensorValue t) {
|
||||
throw new UnsupportedOperationException("Insert not supported for views");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ViewSensorValue> update(ViewSensorValue t) {
|
||||
throw new UnsupportedOperationException("Update not supported for views");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ViewSensorValue> delete(Integer id) {
|
||||
throw new UnsupportedOperationException("Delete not supported for views");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<RowSet<Row>> testConnection() {
|
||||
return pool.query("SELECT 1").execute();
|
||||
}
|
||||
|
||||
public <T> Future<List<T>> execute(String query, Class<T> clazz,
|
||||
Handler<List<T>> onSuccess, Handler<Throwable> onFailure) {
|
||||
return pool.query(query).execute()
|
||||
.map(rows -> {
|
||||
List<T> results = new ArrayList<>();
|
||||
for (Row row : rows) {
|
||||
try {
|
||||
Constructor<T> 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());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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 <T> String getTableName(Class<T> 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 <T> QueryBuilder select(Class<T> 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 <T> QueryBuilder where(QueryBuilder qb, T object) {
|
||||
if (qb == null || object == null) {
|
||||
throw new IllegalArgumentException("QueryBuilder and object cannot be null");
|
||||
}
|
||||
|
||||
List<String> 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 <T> 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 <T> 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 <T> 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<String> column, Optional<String> order) {
|
||||
column.ifPresent(c -> {
|
||||
sort = "ORDER BY " + c + " ";
|
||||
order.ifPresent(o -> {
|
||||
sort += o.equalsIgnoreCase("asc") ? "ASC" : "DESC" + " ";
|
||||
});
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBuilder limit(Optional<Integer> 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() + ";";
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
+ "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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 + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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 + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.miarma.contaminus.db;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.vertx.core.Future;
|
||||
|
||||
public interface DataAccessObject<T, ID> {
|
||||
Future<List<T>> getAll();
|
||||
Future<T> getById(ID id);
|
||||
Future<T> insert(T t);
|
||||
Future<T> update(T t);
|
||||
Future<T> delete(ID id);
|
||||
}
|
||||
@@ -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<RowSet<Row>> testConnection() {
|
||||
return pool.query("SELECT 1").execute();
|
||||
}
|
||||
|
||||
public <T> Future<List<T>> execute(String query, Class<T> clazz, Handler<List<T>> onSuccess,
|
||||
Handler<Throwable> onFailure) {
|
||||
return pool.query(query).execute().map(rows -> {
|
||||
List<T> results = new ArrayList<>();
|
||||
for (Row row : rows) {
|
||||
try {
|
||||
Constructor<T> 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 <T> Future<T> executeOne(String query, Class<T> clazz, Handler<T> onSuccess, Handler<Throwable> onFailure) {
|
||||
return pool.query(query).execute().map(rows -> {
|
||||
for (Row row : rows) {
|
||||
try {
|
||||
Constructor<T> 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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
357
backend/src/main/java/net/miarma/contaminus/db/QueryBuilder.java
Normal file
357
backend/src/main/java/net/miarma/contaminus/db/QueryBuilder.java
Normal file
@@ -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 <T> String getTableName(Class<T> 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 <T> QueryBuilder select(Class<T> 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<String, String> filters) {
|
||||
if (filters == null || filters.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
Set<String> validFields = entityClass != null
|
||||
? Arrays.stream(entityClass.getDeclaredFields()).map(Field::getName).collect(Collectors.toSet())
|
||||
: Collections.emptySet();
|
||||
|
||||
List<String> conditions = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, String> 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 <T> QueryBuilder where(T object) {
|
||||
if (object == null) {
|
||||
throw new IllegalArgumentException("Object cannot be null");
|
||||
}
|
||||
|
||||
Set<String> validFields = entityClass != null
|
||||
? Arrays.stream(entityClass.getDeclaredFields()).map(Field::getName).collect(Collectors.toSet())
|
||||
: Collections.emptySet();
|
||||
|
||||
List<String> 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 <T> 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 <T> 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 <T> 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 <T> 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<String> column, Optional<String> 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<Integer> limitParam) {
|
||||
limitParam.ifPresent(param -> limit = "LIMIT " + param + " ");
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBuilder offset(Optional<Integer> 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() + ";";
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import io.vertx.sqlclient.Row;
|
||||
import net.miarma.contaminus.common.Table;
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.vertx.sqlclient.Row;
|
||||
@@ -6,7 +6,8 @@ import net.miarma.contaminus.common.Table;
|
||||
import net.miarma.contaminus.util.DateParser;
|
||||
|
||||
@Table("v_latest_values")
|
||||
public class DeviceLatestValuesView {
|
||||
public class ViewLatestValues {
|
||||
|
||||
private String deviceId;
|
||||
private Integer sensorId;
|
||||
private String sensorType;
|
||||
@@ -15,14 +16,15 @@ public class DeviceLatestValuesView {
|
||||
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 DeviceLatestValuesView() {}
|
||||
public ViewLatestValues() {}
|
||||
|
||||
public DeviceLatestValuesView(Row row) {
|
||||
public ViewLatestValues(Row row) {
|
||||
this.deviceId = row.getString("deviceId");
|
||||
this.sensorId = row.getInteger("sensorId");
|
||||
this.sensorType = row.getString("sensorType");
|
||||
@@ -31,14 +33,15 @@ public class DeviceLatestValuesView {
|
||||
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 DeviceLatestValuesView(String deviceId, Integer sensorId, String sensorType, String unit, Integer sensorStatus,
|
||||
Long sensorTimestamp, Float temperature, Float humidity, Float carbonMonoxide, Float lat, Float lon,
|
||||
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;
|
||||
@@ -87,6 +90,10 @@ public class DeviceLatestValuesView {
|
||||
return humidity;
|
||||
}
|
||||
|
||||
public Float getPressure() {
|
||||
return pressure;
|
||||
}
|
||||
|
||||
public Float getCarbonMonoxide() {
|
||||
return carbonMonoxide;
|
||||
}
|
||||
@@ -103,10 +110,62 @@ public class DeviceLatestValuesView {
|
||||
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, sensorId, sensorStatus,
|
||||
sensorTimestamp, sensorType, temperature, unit);
|
||||
return Objects.hash(airValuesTimestamp, carbonMonoxide, deviceId, humidity, lat, lon, pressure, sensorId,
|
||||
sensorStatus, sensorTimestamp, sensorType, temperature, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,12 +176,12 @@ public class DeviceLatestValuesView {
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
DeviceLatestValuesView other = (DeviceLatestValuesView) obj;
|
||||
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(sensorId, other.sensorId)
|
||||
&& Objects.equals(sensorStatus, other.sensorStatus)
|
||||
&& 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);
|
||||
@@ -130,13 +189,13 @@ public class DeviceLatestValuesView {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceLatestValuesView [deviceId=" + deviceId + ", sensorId=" + sensorId + ", sensorType=" + sensorType
|
||||
return "ViewLatestValues [deviceId=" + deviceId + ", sensorId=" + sensorId + ", sensorType=" + sensorType
|
||||
+ ", unit=" + unit + ", sensorStatus=" + sensorStatus + ", sensorTimestamp=" + sensorTimestamp
|
||||
+ ", temperature=" + temperature + ", humidity=" + humidity + ", carbonMonoxide=" + carbonMonoxide
|
||||
+ ", lat=" + lat + ", lon=" + lon + ", airValuesTimestamp=" + airValuesTimestamp + "]";
|
||||
+ ", temperature=" + temperature + ", humidity=" + humidity + ", pressure=" + pressure
|
||||
+ ", carbonMonoxide=" + carbonMonoxide + ", lat=" + lat + ", lon=" + lon + ", airValuesTimestamp="
|
||||
+ airValuesTimestamp + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -7,7 +7,7 @@ import net.miarma.contaminus.common.Table;
|
||||
import net.miarma.contaminus.util.DateParser;
|
||||
|
||||
@Table("v_pollution_map")
|
||||
public class DevicePollutionMap {
|
||||
public class ViewPollutionMap {
|
||||
private String deviceId;
|
||||
private String deviceName;
|
||||
private Float lat;
|
||||
@@ -15,9 +15,9 @@ public class DevicePollutionMap {
|
||||
private Float carbonMonoxide;
|
||||
private Long timestamp;
|
||||
|
||||
public DevicePollutionMap() {}
|
||||
public ViewPollutionMap() {}
|
||||
|
||||
public DevicePollutionMap(Row row) {
|
||||
public ViewPollutionMap(Row row) {
|
||||
this.deviceId = row.getString("deviceId");
|
||||
this.deviceName = row.getString("deviceName");
|
||||
this.lat = row.getFloat("lat");
|
||||
@@ -26,7 +26,7 @@ public class DevicePollutionMap {
|
||||
this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp"));
|
||||
}
|
||||
|
||||
public DevicePollutionMap(String deviceId, String deviceName, Float lat, Float lon, Float carbonMonoxide,
|
||||
public ViewPollutionMap(String deviceId, String deviceName, Float lat, Float lon, Float carbonMonoxide,
|
||||
Long timestamp) {
|
||||
super();
|
||||
this.deviceId = deviceId;
|
||||
@@ -61,6 +61,32 @@ public class DevicePollutionMap {
|
||||
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);
|
||||
@@ -74,7 +100,7 @@ public class DevicePollutionMap {
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
DevicePollutionMap other = (DevicePollutionMap) obj;
|
||||
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);
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -7,16 +7,16 @@ import net.miarma.contaminus.common.Table;
|
||||
import net.miarma.contaminus.util.DateParser;
|
||||
|
||||
@Table("v_sensor_history_by_device")
|
||||
public class DeviceSensorHistory {
|
||||
public class ViewSensorHistory {
|
||||
private String deviceId;
|
||||
private String deviceName;
|
||||
private Float value;
|
||||
private String valueType;
|
||||
private Long timestamp;
|
||||
|
||||
public DeviceSensorHistory() {}
|
||||
public ViewSensorHistory() {}
|
||||
|
||||
public DeviceSensorHistory(Row row) {
|
||||
public ViewSensorHistory(Row row) {
|
||||
this.deviceId = row.getString("deviceId");
|
||||
this.deviceName = row.getString("deviceName");
|
||||
this.value = row.getFloat("value");
|
||||
@@ -24,7 +24,7 @@ public class DeviceSensorHistory {
|
||||
this.timestamp = DateParser.parseDate(row.getLocalDateTime("timestamp"));
|
||||
}
|
||||
|
||||
public DeviceSensorHistory(String deviceId, String deviceName, Float value, String valueType, Long timestamp) {
|
||||
public ViewSensorHistory(String deviceId, String deviceName, Float value, String valueType, Long timestamp) {
|
||||
super();
|
||||
this.deviceId = deviceId;
|
||||
this.deviceName = deviceName;
|
||||
@@ -53,6 +53,28 @@ public class DeviceSensorHistory {
|
||||
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);
|
||||
@@ -66,7 +88,7 @@ public class DeviceSensorHistory {
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
DeviceSensorHistory other = (DeviceSensorHistory) obj;
|
||||
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);
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -7,7 +7,7 @@ import net.miarma.contaminus.common.Table;
|
||||
import net.miarma.contaminus.util.DateParser;
|
||||
|
||||
@Table("v_sensor_values")
|
||||
public class DeviceSensorValue {
|
||||
public class ViewSensorValue {
|
||||
private Integer sensorId;
|
||||
private String deviceId;
|
||||
private String sensorType;
|
||||
@@ -15,14 +15,15 @@ public class DeviceSensorValue {
|
||||
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 DeviceSensorValue() {}
|
||||
public ViewSensorValue() {}
|
||||
|
||||
public DeviceSensorValue(Row row) {
|
||||
public ViewSensorValue(Row row) {
|
||||
this.sensorId = row.getInteger("sensorId");
|
||||
this.deviceId = row.getString("deviceId");
|
||||
this.sensorType = row.getString("sensorType");
|
||||
@@ -30,14 +31,15 @@ public class DeviceSensorValue {
|
||||
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 DeviceSensorValue(Integer sensorId, String deviceId, String sensorType, String unit, Integer sensorStatus,
|
||||
Float temperature, Float humidity, Float carbonMonoxide, Float lat, Float lon, Long 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;
|
||||
@@ -46,6 +48,7 @@ public class DeviceSensorValue {
|
||||
this.sensorStatus = sensorStatus;
|
||||
this.temperature = temperature;
|
||||
this.humidity = humidity;
|
||||
this.pressure = pressure;
|
||||
this.carbonMonoxide = carbonMonoxide;
|
||||
this.lat = lat;
|
||||
this.lon = lon;
|
||||
@@ -80,6 +83,10 @@ public class DeviceSensorValue {
|
||||
return humidity;
|
||||
}
|
||||
|
||||
public Float getPressure() {
|
||||
return pressure;
|
||||
}
|
||||
|
||||
public Float getCarbonMonoxide() {
|
||||
return carbonMonoxide;
|
||||
}
|
||||
@@ -96,9 +103,59 @@ public class DeviceSensorValue {
|
||||
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, sensorId, sensorStatus, sensorType,
|
||||
return Objects.hash(carbonMonoxide, deviceId, humidity, lat, lon, pressure, sensorId, sensorStatus, sensorType,
|
||||
temperature, timestamp, unit);
|
||||
}
|
||||
|
||||
@@ -110,22 +167,23 @@ public class DeviceSensorValue {
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
DeviceSensorValue other = (DeviceSensorValue) obj;
|
||||
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(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);
|
||||
&& 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 "DeviceSensorValue [sensorId=" + sensorId + ", deviceId=" + deviceId + ", sensorType=" + sensorType
|
||||
return "ViewSensorValue [sensorId=" + sensorId + ", deviceId=" + deviceId + ", sensorType=" + sensorType
|
||||
+ ", unit=" + unit + ", sensorStatus=" + sensorStatus + ", temperature=" + temperature + ", humidity="
|
||||
+ humidity + ", carbonMonoxide=" + carbonMonoxide + ", lat=" + lat + ", lon=" + lon + ", timestamp="
|
||||
+ timestamp + "]";
|
||||
+ humidity + ", pressure=" + pressure + ", carbonMonoxide=" + carbonMonoxide + ", lat=" + lat + ", lon="
|
||||
+ lon + ", timestamp=" + timestamp + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.database.entities;
|
||||
package net.miarma.contaminus.entities;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -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<Void> startPromise) {
|
||||
Constants.LOGGER.info("📡 Iniciando DataLayerAPIVerticle...");
|
||||
|
||||
dbManager = DatabaseManager.getInstance(pool);
|
||||
|
||||
Router router = Router.router(vertx);
|
||||
Set<HttpMethod> allowedMethods = new HashSet<>(
|
||||
Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); // Por ejemplo
|
||||
Set<String> 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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Void> startPromise) {
|
||||
Constants.LOGGER.info("📡 Iniciando LogicApiVerticle...");
|
||||
|
||||
Router router = Router.router(vertx);
|
||||
Set<HttpMethod> allowedMethods = new HashSet<>(
|
||||
Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); // Por ejemplo
|
||||
Set<String> 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<Device[]> resultList = Promise.promise();
|
||||
resultList.future().onComplete(complete -> {
|
||||
if(complete.succeeded()) {
|
||||
List<Device> 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<Sensor[]> resultList = Promise.promise();
|
||||
resultList.future().onComplete(result -> {
|
||||
if (result.succeeded()) {
|
||||
Sensor[] sensors = result.result();
|
||||
List<Sensor> 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<Actuator[]> resultList = Promise.promise();
|
||||
resultList.future().onComplete(result -> {
|
||||
if (result.succeeded()) {
|
||||
Actuator[] devices = result.result();
|
||||
List<Actuator> 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<DeviceLatestValuesView[]> resultList = Promise.promise();
|
||||
resultList.future().onComplete(complete -> {
|
||||
if (complete.succeeded()) {
|
||||
List<DeviceLatestValuesView> 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<DevicePollutionMap[]> resultList = Promise.promise();
|
||||
|
||||
resultList.future().onComplete(complete -> {
|
||||
if (complete.succeeded()) {
|
||||
List<DevicePollutionMap> 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<DeviceSensorHistory[]> resultList = Promise.promise();
|
||||
|
||||
resultList.future().onComplete(complete -> {
|
||||
if (complete.succeeded()) {
|
||||
List<DeviceSensorHistory> 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<DeviceSensorValue[]> resultList = Promise.promise();
|
||||
|
||||
resultList.future().onComplete(complete -> {
|
||||
if (complete.succeeded()) {
|
||||
List<DeviceSensorValue> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<Void> 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<HttpMethod> allowedMethods = new HashSet<>(
|
||||
Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); // Por ejemplo
|
||||
Set<String> 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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Void> startPromise) {
|
||||
Constants.LOGGER.info("📡 Iniciando LogicApiVerticle...");
|
||||
|
||||
Router router = Router.router(vertx);
|
||||
Set<HttpMethod> allowedMethods = new HashSet<>(
|
||||
Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS));
|
||||
Set<String> 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<ViewLatestValues[]> resultList = Promise.promise();
|
||||
resultList.future().onComplete(complete -> {
|
||||
if (complete.succeeded()) {
|
||||
List<ViewLatestValues> 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<ViewPollutionMap[]> resultList = Promise.promise();
|
||||
|
||||
resultList.future().onComplete(complete -> {
|
||||
if (complete.succeeded()) {
|
||||
List<ViewPollutionMap> 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<ViewSensorHistory[]> resultList = Promise.promise();
|
||||
|
||||
resultList.future().onComplete(complete -> {
|
||||
if (complete.succeeded()) {
|
||||
List<ViewSensorHistory> 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<ViewSensorValue[]> resultList = Promise.promise();
|
||||
|
||||
resultList.future().onComplete(complete -> {
|
||||
if (complete.succeeded()) {
|
||||
List<ViewSensorValue> 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);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.server;
|
||||
package net.miarma.contaminus.verticles;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -52,7 +52,6 @@ public class MainVerticle extends AbstractVerticle {
|
||||
@Override
|
||||
public void start(Promise<Void> startPromise) {
|
||||
try {
|
||||
System.setProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager");
|
||||
init();
|
||||
deployVerticles(startPromise);
|
||||
} catch (Exception e) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.miarma.contaminus.server;
|
||||
package net.miarma.contaminus.verticles;
|
||||
|
||||
import io.vertx.core.AbstractVerticle;
|
||||
import io.vertx.core.Promise;
|
||||
@@ -4,7 +4,7 @@ db.host=localhost
|
||||
db.port=3306
|
||||
db.name=dad
|
||||
db.user=root
|
||||
db.pwd=root
|
||||
db.password=root
|
||||
dp.poolSize=5
|
||||
|
||||
# HTTP Server Configuration
|
||||
|
||||
20
backend/src/main/resources/logback.xml
Normal file
20
backend/src/main/resources/logback.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>
|
||||
%cyan([%d{HH:mm:ss}]) %highlight(%-5level) %green(%logger{20}) - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
|
||||
<logger name="io.netty" level="WARN"/>
|
||||
<logger name="io.vertx" level="INFO"/>
|
||||
<logger name="io.vertx.core.impl.launcher" level="INFO"/>
|
||||
<logger name="io.vertx.core.logging" level="INFO"/>
|
||||
|
||||
</configuration>
|
||||
@@ -51,8 +51,8 @@ const SummaryCardsContent = () => {
|
||||
let coData = data[1];
|
||||
let tempData = data[2];
|
||||
|
||||
let lastTime = DateParser.timestampToString(coData.airValuesTimestamp);
|
||||
let lastDate = new Date(coData.airValuesTimestamp);
|
||||
let lastTime = DateParser.timestampToString(coData.timestamp);
|
||||
let lastDate = new Date(coData.timestamp);
|
||||
|
||||
CardsData[0].content = tempData.temperature + "°C";
|
||||
CardsData[0].status = "Temperatura actual";
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <HTTPClient.h>
|
||||
#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);
|
||||
|
||||
@@ -9,8 +9,8 @@ String serializeSensorValue(
|
||||
const BME280Data_t &bme,
|
||||
const MQ7Data_t &mq7,
|
||||
const GPSData_t &gps,
|
||||
long timestamp
|
||||
) {
|
||||
long timestamp)
|
||||
{
|
||||
DynamicJsonDocument doc(1024);
|
||||
|
||||
doc["sensorId"] = sensorId;
|
||||
@@ -32,7 +32,8 @@ String serializeSensorValue(
|
||||
return output;
|
||||
}
|
||||
|
||||
String serializeActuatorStatus(const int actuatorId, const String &deviceId, const int status, const long timestamp) {
|
||||
String serializeActuatorStatus(const int actuatorId, const String &deviceId, const int status, const long timestamp)
|
||||
{
|
||||
DynamicJsonDocument doc(512);
|
||||
|
||||
doc["actuatorId"] = actuatorId;
|
||||
@@ -46,7 +47,8 @@ String serializeActuatorStatus(const int actuatorId, const String &deviceId, con
|
||||
return output;
|
||||
}
|
||||
|
||||
String serializeDevice(const String &deviceId, int groupId, const String &deviceName) {
|
||||
String serializeDevice(const String &deviceId, int groupId, const String &deviceName)
|
||||
{
|
||||
DynamicJsonDocument doc(512);
|
||||
|
||||
doc["deviceId"] = deviceId;
|
||||
@@ -59,22 +61,26 @@ String serializeDevice(const String &deviceId, int groupId, const String &device
|
||||
return output;
|
||||
}
|
||||
|
||||
void deserializeSensorValue(HTTPClient &http, int httpResponseCode) {
|
||||
if (httpResponseCode > 0) {
|
||||
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) {
|
||||
if (error)
|
||||
{
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return;
|
||||
}
|
||||
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
for (JsonObject sensor : array) {
|
||||
for (JsonObject sensor : array)
|
||||
{
|
||||
int sensorId = sensor["sensorId"];
|
||||
String deviceId = sensor["deviceId"];
|
||||
String sensorType = sensor["sensorType"];
|
||||
@@ -92,28 +98,34 @@ void deserializeSensorValue(HTTPClient &http, int httpResponseCode) {
|
||||
sensorId, deviceId.c_str(), sensorType.c_str(), unit.c_str(), sensorStatus,
|
||||
temperature, humidity, carbonMonoxide, lat, lon, timestamp);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("Error code: ");
|
||||
Serial.println(httpResponseCode);
|
||||
}
|
||||
}
|
||||
|
||||
void deserializeActuatorStatus(HTTPClient &http, int httpResponseCode) {
|
||||
if (httpResponseCode > 0) {
|
||||
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) {
|
||||
if (error)
|
||||
{
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return;
|
||||
}
|
||||
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
for (JsonObject actuator : array) {
|
||||
for (JsonObject actuator : array)
|
||||
{
|
||||
int actuatorId = actuator["actuatorId"];
|
||||
String deviceId = actuator["deviceId"];
|
||||
int status = actuator["status"];
|
||||
@@ -123,28 +135,34 @@ void deserializeActuatorStatus(HTTPClient &http, int httpResponseCode) {
|
||||
Serial.printf(" ID: %d\n Device: %s\n Status: %d\n Time: %ld\n\n",
|
||||
actuatorId, deviceId.c_str(), status, timestamp);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("Error code: ");
|
||||
Serial.println(httpResponseCode);
|
||||
}
|
||||
}
|
||||
|
||||
void deserializeDevice(HTTPClient &http, int httpResponseCode) {
|
||||
if (httpResponseCode > 0) {
|
||||
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) {
|
||||
if (error)
|
||||
{
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return;
|
||||
}
|
||||
|
||||
JsonArray array = doc.as<JsonArray>();
|
||||
for (JsonObject device : array) {
|
||||
for (JsonObject device : array)
|
||||
{
|
||||
String deviceId = device["deviceId"];
|
||||
int groupId = device["groupId"];
|
||||
String deviceName = device["deviceName"];
|
||||
@@ -152,7 +170,9 @@ void deserializeDevice(HTTPClient &http, int httpResponseCode) {
|
||||
Serial.println("Device deserialized:");
|
||||
Serial.printf(" ID: %s\n Group: %d\n Name: %s\n\n", deviceId.c_str(), groupId, deviceName.c_str());
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("Error code: ");
|
||||
Serial.println(httpResponseCode);
|
||||
}
|
||||
|
||||
@@ -6,9 +6,12 @@ void getRequest(const String url, String &response)
|
||||
{
|
||||
httpClient.begin(url);
|
||||
int httpCode = httpClient.GET();
|
||||
if (httpCode > 0) {
|
||||
if (httpCode > 0)
|
||||
{
|
||||
response = httpClient.getString();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
response = "Error: " + String(httpCode);
|
||||
}
|
||||
httpClient.end();
|
||||
@@ -19,9 +22,12 @@ 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) {
|
||||
if (httpCode > 0)
|
||||
{
|
||||
response = httpClient.getString();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
response = "Error: " + String(httpCode);
|
||||
}
|
||||
httpClient.end();
|
||||
|
||||
@@ -12,7 +12,8 @@ void OnMqttReceived(char *topic, byte *payload, unsigned int length)
|
||||
|
||||
String content = "";
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
content.concat((char)payload[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,24 +6,28 @@
|
||||
|
||||
WiFiClient wifiClient;
|
||||
|
||||
void setColor(uint8_t r, uint8_t g, uint8_t b) {
|
||||
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);
|
||||
|
||||
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) {
|
||||
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);
|
||||
@@ -80,4 +84,3 @@ int setupWifi()
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ void BME280_Init()
|
||||
|
||||
bme.setSettings(settings);
|
||||
|
||||
while (!bme.begin());
|
||||
while (!bme.begin())
|
||||
;
|
||||
}
|
||||
|
||||
BME280Data_t BME280_Read()
|
||||
@@ -31,4 +32,3 @@ BME280Data_t BME280_Read()
|
||||
bme.read(p, t, h, tUnit, pUnit);
|
||||
return {p, t, h};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -91,7 +97,8 @@ void readGPS()
|
||||
|
||||
void writeMatrix(const char *message)
|
||||
{
|
||||
if (currentMessage == message) return;
|
||||
if (currentMessage == message)
|
||||
return;
|
||||
currentMessage = message;
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -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()
|
||||
@@ -126,7 +144,8 @@ uint32_t getChipID()
|
||||
chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
Serial.print("Chip ID: "); Serial.println(chipId, HEX);
|
||||
Serial.print("Chip ID: ");
|
||||
Serial.println(chipId, HEX);
|
||||
#endif
|
||||
return chipId;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user