diff --git a/backend/pom.xml b/backend/pom.xml index 848550d..fec773d 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -55,6 +55,13 @@ 2.12.1 + + + org.jboss.logmanager + jboss-logmanager + 3.1.1.Final + + diff --git a/backend/src/main/java/net/miarma/contaminus/common/ConfigManager.java b/backend/src/main/java/net/miarma/contaminus/common/ConfigManager.java index 98086bf..8277c21 100644 --- a/backend/src/main/java/net/miarma/contaminus/common/ConfigManager.java +++ b/backend/src/main/java/net/miarma/contaminus/common/ConfigManager.java @@ -4,49 +4,20 @@ import java.io.*; import java.util.Properties; public class ConfigManager { - private static ConfigManager instance; + private static final ConfigManager INSTANCE = new ConfigManager(); private final File configFile; private final Properties config; + private static final String CONFIG_FILE_NAME = "config.properties"; private ConfigManager() { - this.configFile = new File(Constants.CONFIG_FILE); + String path = getBaseDir() + CONFIG_FILE_NAME; + this.configFile = new File(path); this.config = new Properties(); - - if (!configFile.exists()) { - try { - createFiles(); - } catch (IOException e) { - Constants.LOGGER.error("Error creating configuration files: ", e); - } - } - loadConfig(); } - public static synchronized ConfigManager getInstance() { - if (instance == null) { - instance = new ConfigManager(); - } - return instance; - } - - private void createFiles() throws IOException { - File baseDir = new File(Constants.BASE_DIR); - if (!baseDir.exists()) baseDir.mkdirs(); - - try (InputStream defaultConfigStream = getClass().getClassLoader().getResourceAsStream("default.properties"); - FileOutputStream fos = new FileOutputStream(configFile)) { - - if (defaultConfigStream != null) { - byte[] buffer = new byte[1024]; - int bytesRead; - while ((bytesRead = defaultConfigStream.read(buffer)) != -1) { - fos.write(buffer, 0, bytesRead); - } - } else { - Constants.LOGGER.error("File not found: default.properties"); - } - } + public static ConfigManager getInstance() { + return INSTANCE; } private void loadConfig() { @@ -56,17 +27,71 @@ public class ConfigManager { Constants.LOGGER.error("Error loading configuration file: ", e); } } + + public File getConfigFile() { + return configFile; + } + public String getJdbcUrl() { + return String.format("%s://%s:%s/%s", + config.getProperty("db.protocol"), + config.getProperty("db.host"), + config.getProperty("db.port"), + config.getProperty("db.name")); + } + + public String getHost() { + return this.getStringProperty("inet.host"); + } + + public int getDataApiPort() { + return this.getIntProperty("data-api.port"); + } + + public int getLogicApiPort() { + return this.getIntProperty("logic-api.port"); + } + + public int getWebserverPort() { + return this.getIntProperty("webserver.port"); + } + + public String getHomeDir() { + return getOS() == OSType.WINDOWS ? + "C:/Users/" + System.getProperty("user.name") + "/" : + System.getProperty("user.home").contains("root") ? "/root/" : + "/home/" + System.getProperty("user.name") + "/"; + } + + public String getBaseDir() { + return getHomeDir() + + (getOS() == OSType.WINDOWS ? ".contaminus/" : + getOS() == OSType.LINUX ? ".config/contaminus/" : + ".contaminus/"); + } + + public static OSType getOS() { + String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("win")) { + return OSType.WINDOWS; + } else if (os.contains("nix") || os.contains("nux")) { + return OSType.LINUX; + } else { + return OSType.INVALID_OS; + } + } + public String getStringProperty(String key) { return config.getProperty(key); } public int getIntProperty(String key) { - return Integer.parseInt(config.getProperty(key)); - } + String value = config.getProperty(key); + return value != null ? Integer.parseInt(value) : 10; + } public boolean getBooleanProperty(String key) { - return Boolean.parseBoolean(config.getProperty(key)); + return Boolean.parseBoolean(config.getProperty(key)); } public void setProperty(String key, String value) { diff --git a/backend/src/main/java/net/miarma/contaminus/common/Constants.java b/backend/src/main/java/net/miarma/contaminus/common/Constants.java index 9da4d47..c3d9b3f 100644 --- a/backend/src/main/java/net/miarma/contaminus/common/Constants.java +++ b/backend/src/main/java/net/miarma/contaminus/common/Constants.java @@ -6,44 +6,38 @@ import io.vertx.core.impl.logging.LoggerFactory; public class Constants { public static final String APP_NAME = "ContaminUS"; public static final String API_PREFIX = "/api/v1"; - public static final String HOME_DIR = SystemInfo.getOS() == OSType.WINDOWS ? - "C:/Users/" + System.getProperty("user.name") + "/" : - System.getProperty("user.home").contains("root") ? "/root/" : - "/home/" + System.getProperty("user.name") + "/"; - public static final String BASE_DIR = HOME_DIR + - (SystemInfo.getOS() == OSType.WINDOWS ? ".contaminus" : - SystemInfo.getOS() == OSType.LINUX ? ".config" + "/" + - "contaminus" : null); - public static final String CONFIG_FILE = BASE_DIR + "/" + "config.properties"; - public static final Logger LOGGER = LoggerFactory.getLogger(APP_NAME); + public static Logger LOGGER = LoggerFactory.getLogger(Constants.APP_NAME); + + /* API Endpoints */ public static final String GET_GROUPS = API_PREFIX + "/groups"; - 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 POST_GROUPS = API_PREFIX + "/groups"; public static final String PUT_GROUP_BY_ID = API_PREFIX + "/groups/:groupId"; public static final String GET_DEVICES = API_PREFIX + "/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 POST_DEVICES = API_PREFIX + "/devices"; public static final String PUT_DEVICE_BY_ID = API_PREFIX + "/devices/:deviceId"; - 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_SENSORS = API_PREFIX + "/sensors"; - 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 POST_SENSORS = API_PREFIX + "/sensors"; public static final String PUT_SENSOR_BY_ID = API_PREFIX + "/sensors/:sensorId"; public static final String GET_ACTUATORS = API_PREFIX + "/actuators"; - public static final String GET_ACTUATOR_BY_ID = API_PREFIX + "/actuators/:actuatorId"; public static final String POST_ACTUATORS = API_PREFIX + "/actuators"; public static final String PUT_ACTUATOR_BY_ID = API_PREFIX + "/actuators/:actuatorId"; + /* Bussiness Logic API */ + public static final String GET_GROUP_BY_ID = API_PREFIX + "/groups/:groupId"; + public static final String GET_GROUP_DEVICES = API_PREFIX + "/groups/:groupId/devices"; + public static final String GET_DEVICE_BY_ID = API_PREFIX + "/devices/:deviceId"; + public static final String GET_DEVICE_SENSORS = API_PREFIX + "/devices/:deviceId/sensors"; + public static final String GET_DEVICE_ACTUATORS = API_PREFIX + "/devices/:deviceId/actuators"; + public static final String GET_DEVICE_LATEST_VALUES = API_PREFIX + "/devices/:deviceId/latest"; + public static final String GET_DEVICE_POLLUTION_MAP = API_PREFIX + "/devices/:deviceId/pollution-map"; + public static final String GET_DEVICE_HISTORY = API_PREFIX + "/devices/:deviceId/history"; + public static final String GET_SENSOR_BY_ID = API_PREFIX + "/sensors/:sensorId"; + public static final String GET_SENSOR_VALUES = API_PREFIX + "/sensors/:sensorId/values"; + public static final String GET_ACTUATOR_BY_ID = API_PREFIX + "/actuators/:actuatorId"; private Constants() { throw new AssertionError("Utility class cannot be instantiated."); diff --git a/backend/src/main/java/net/miarma/contaminus/common/Host.java b/backend/src/main/java/net/miarma/contaminus/common/Host.java deleted file mode 100644 index ba1eeed..0000000 --- a/backend/src/main/java/net/miarma/contaminus/common/Host.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.miarma.contaminus.common; - -public class Host { - static ConfigManager configManager = ConfigManager.getInstance(); - static String host = configManager.getStringProperty("inet.host"); - static String origin = configManager.getStringProperty("inet.origin"); - static int apiPort = configManager.getIntProperty("api.port"); - static int webserverPort = configManager.getIntProperty("webserver.port"); - - public static String getHost() { - return host; - } - - public static int getApiPort() { - return apiPort; - } - - public static int getWebserverPort() { - return webserverPort; - } -} diff --git a/backend/src/main/java/net/miarma/contaminus/common/SystemInfo.java b/backend/src/main/java/net/miarma/contaminus/common/SystemInfo.java deleted file mode 100644 index 72dc3a4..0000000 --- a/backend/src/main/java/net/miarma/contaminus/common/SystemInfo.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.miarma.contaminus.common; - -public class SystemInfo { - public static OSType getOS() { - String envProperty = System.getProperty("os.name").toLowerCase(); - if(envProperty.contains("windows")) { - return OSType.WINDOWS; - } else if(envProperty.contains("linux")) { - return OSType.LINUX; - } else { - return OSType.INVALID_OS; - } - } -} diff --git a/backend/src/main/java/net/miarma/contaminus/common/Table.java b/backend/src/main/java/net/miarma/contaminus/common/Table.java new file mode 100644 index 0000000..7754714 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/common/Table.java @@ -0,0 +1,12 @@ +package net.miarma.contaminus.common; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) // aplica a clases/interfaces +@Retention(RetentionPolicy.RUNTIME) // disponible en tiempo de ejecuciΓ³n +public @interface Table { + String value(); +} diff --git a/backend/src/main/java/net/miarma/contaminus/common/entities/Actuator.java b/backend/src/main/java/net/miarma/contaminus/common/entities/Actuator.java deleted file mode 100644 index 05bc49f..0000000 --- a/backend/src/main/java/net/miarma/contaminus/common/entities/Actuator.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.miarma.contaminus.common.entities; - -public class Actuator { - -} diff --git a/backend/src/main/java/net/miarma/contaminus/common/entities/COValue.java b/backend/src/main/java/net/miarma/contaminus/common/entities/COValue.java deleted file mode 100644 index 7e1c521..0000000 --- a/backend/src/main/java/net/miarma/contaminus/common/entities/COValue.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.miarma.contaminus.common.entities; - -public class COValue { - -} diff --git a/backend/src/main/java/net/miarma/contaminus/common/entities/Device.java b/backend/src/main/java/net/miarma/contaminus/common/entities/Device.java deleted file mode 100644 index ed3fc0a..0000000 --- a/backend/src/main/java/net/miarma/contaminus/common/entities/Device.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.miarma.contaminus.common.entities; - -public class Device { - -} diff --git a/backend/src/main/java/net/miarma/contaminus/common/entities/GpsValue.java b/backend/src/main/java/net/miarma/contaminus/common/entities/GpsValue.java deleted file mode 100644 index ea46779..0000000 --- a/backend/src/main/java/net/miarma/contaminus/common/entities/GpsValue.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.miarma.contaminus.common.entities; - -public class GpsValue { - -} diff --git a/backend/src/main/java/net/miarma/contaminus/common/entities/Group.java b/backend/src/main/java/net/miarma/contaminus/common/entities/Group.java deleted file mode 100644 index 9b96951..0000000 --- a/backend/src/main/java/net/miarma/contaminus/common/entities/Group.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.miarma.contaminus.common.entities; - -public class Group { - -} diff --git a/backend/src/main/java/net/miarma/contaminus/common/entities/Sensor.java b/backend/src/main/java/net/miarma/contaminus/common/entities/Sensor.java deleted file mode 100644 index 1799081..0000000 --- a/backend/src/main/java/net/miarma/contaminus/common/entities/Sensor.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.miarma.contaminus.common.entities; - -public class Sensor { - -} diff --git a/backend/src/main/java/net/miarma/contaminus/common/entities/WeatherValue.java b/backend/src/main/java/net/miarma/contaminus/common/entities/WeatherValue.java deleted file mode 100644 index 8286952..0000000 --- a/backend/src/main/java/net/miarma/contaminus/common/entities/WeatherValue.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.miarma.contaminus.common.entities; - -public class WeatherValue { - -} diff --git a/backend/src/main/java/net/miarma/contaminus/database/DatabaseManager.java b/backend/src/main/java/net/miarma/contaminus/database/DatabaseManager.java index c40c9b7..9c1d350 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/DatabaseManager.java +++ b/backend/src/main/java/net/miarma/contaminus/database/DatabaseManager.java @@ -1,30 +1,58 @@ package net.miarma.contaminus.database; -import io.vertx.core.Vertx; -import io.vertx.core.json.JsonObject; +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 net.miarma.contaminus.common.ConfigManager; +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; + } - @SuppressWarnings("deprecation") - public DatabaseManager(Vertx vertx) { - ConfigManager config = ConfigManager.getInstance(); - - JsonObject dbConfig = new JsonObject() - .put("url", config.getStringProperty("db.protocol") + "//" + - config.getStringProperty("db.host") + ":" + - config.getStringProperty("db.port") + "/" + - config.getStringProperty("db.name")) - .put("user", config.getStringProperty("db.user")) - .put("password", config.getStringProperty("db.pwd")) - .put("max_pool_size", config.getStringProperty("db.poolSize")); - - pool = JDBCPool.pool(vertx, dbConfig); + public static synchronized DatabaseManager getInstance(JDBCPool pool) { + if (instance == null) { + instance = new DatabaseManager(pool); + } + return instance; } - public JDBCPool getPool() { - return pool; + public Future> testConnection() { + return pool.query("SELECT 1").execute(); + } + + public Future> execute(String query, Class clazz, + Handler> onSuccess, Handler onFailure) { + return pool.query(query).execute() + .map(rows -> { + List results = new ArrayList<>(); + for (Row row : rows) { + try { + Constructor constructor = clazz.getConstructor(Row.class); + results.add(constructor.newInstance(row)); + } catch (NoSuchMethodException | InstantiationException | + IllegalAccessException | InvocationTargetException e) { + Constants.LOGGER.error("Error instantiating class: " + e.getMessage()); + } + } + return results; + }) + .onComplete(ar -> { + if (ar.succeeded()) { + onSuccess.handle(ar.result()); + } else { + onFailure.handle(ar.cause()); + } + }); } } diff --git a/backend/src/main/java/net/miarma/contaminus/database/QueryBuilder.java b/backend/src/main/java/net/miarma/contaminus/database/QueryBuilder.java index 3a75c85..4b07395 100644 --- a/backend/src/main/java/net/miarma/contaminus/database/QueryBuilder.java +++ b/backend/src/main/java/net/miarma/contaminus/database/QueryBuilder.java @@ -1,87 +1,135 @@ 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 List conditions; private String sort; private String order; private String limit; public QueryBuilder() { this.query = new StringBuilder(); - this.conditions = new ArrayList<>(); } - public static QueryBuilder select(String... columns) { - QueryBuilder qb = new QueryBuilder(); - StringJoiner joiner = new StringJoiner(", "); - for (String column : columns) { - joiner.add(column); + private static String getTableName(Class clazz) { + if (clazz.isAnnotationPresent(Table.class)) { + Table annotation = clazz.getAnnotation(Table.class); + return annotation.value(); // lee el nombre de la tabla desde la annotation } - qb.query.append("SELECT ").append(joiner).append(" "); + throw new IllegalArgumentException("Clase no tiene la anotaciΓ³n @TableName"); + } + + public String getQuery() { + return query.toString(); + } + + public static QueryBuilder select(Class clazz, String... columns) { + 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) { + joiner.add(column); + } + qb.query.append(joiner).append(" "); + } + + qb.query.append("FROM ").append(tableName).append(" "); return qb; } - public static QueryBuilder insert(String table, String... columns) { - QueryBuilder qb = new QueryBuilder(); - StringJoiner joiner = new StringJoiner(", "); - if (columns.length > 0) { - for (String column : columns) { - joiner.add(column); - } - qb.query.append("INSERT INTO ").append(table).append(" (").append(joiner).append(") "); - } else { - qb.query.append("INSERT INTO ").append(table).append(" "); - } - - return qb; - } - - public static QueryBuilder update(String table) { - QueryBuilder qb = new QueryBuilder(); - qb.query.append("UPDATE ").append(table).append(" "); - return qb; - } - - public QueryBuilder set(String column, Object value) { - if(value instanceof String) { - query.append("SET ").append(column).append(" = '").append(value).append("' "); - } else { - query.append("SET ").append(column).append(" = ").append(value).append(" "); - } - return this; - } - - public QueryBuilder values(Object... values) { - StringJoiner joiner = new StringJoiner(", ", "VALUES (", ")"); - for (Object value : values) { - if(value instanceof String) { - joiner.add("'" + value + "'"); - } else if(value == null) { - joiner.add("NULL"); - } - else { - joiner.add(value.toString()); + public static QueryBuilder where(QueryBuilder qb, T object) { + List conditions = new ArrayList<>(); + Class clazz = object.getClass(); + + for (Field field : clazz.getDeclaredFields()) { + field.setAccessible(true); + try { + Object value = field.get(object); + if (value != null) { + if (value instanceof String) { + conditions.add(field.getName() + " = '" + value + "'"); + } else { + conditions.add(field.getName() + " = " + value); + } + } + } catch (IllegalAccessException e) { + Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); } } - this.query.append(joiner).append(" "); - return this; + + if (!conditions.isEmpty()) { + qb.query.append("WHERE ").append(String.join(" AND ", conditions)).append(" "); + } + + return qb; } - public QueryBuilder from(String table) { - query.append("FROM ").append(table).append(" "); - return this; + public static QueryBuilder select(T object, String... columns) { + Class clazz = object.getClass(); + QueryBuilder qb = select(clazz, columns); + return where(qb, object); + } + + + public static QueryBuilder insert(T object) { + 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()); + if(field.get(object) instanceof String) { + values.add("'" + field.get(object) + "'"); + } else { + values.add(field.get(object).toString()); + } + } 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 QueryBuilder where(String conditionsString, Object... values) { - conditionsString = conditionsString.replaceAll("\\?", "%s"); - conditions.add(String.format(conditionsString, values)); - return this; + public static QueryBuilder update(T object) { + 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 { + if(field.get(object) instanceof String) { + joiner.add(field.getName() + " = '" + field.get(object) + "'"); + } else { + joiner.add(field.getName() + " = " + field.get(object).toString()); + } + } catch (IllegalArgumentException | IllegalAccessException e) { + Constants.LOGGER.error("(REFLECTION) Error reading field: " + e.getMessage()); + } + } + qb.query.append(joiner).append(" "); + return qb; } public QueryBuilder orderBy(Optional column, Optional order) { @@ -100,14 +148,6 @@ public class QueryBuilder { } public String build() { - if (!conditions.isEmpty()) { - query.append("WHERE "); - StringJoiner joiner = new StringJoiner(" AND "); - for (String condition : conditions) { - joiner.add(condition); - } - query.append(joiner).append(" "); - } if (order != null && !order.isEmpty()) { query.append(order); } diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/Actuator.java b/backend/src/main/java/net/miarma/contaminus/database/entities/Actuator.java new file mode 100644 index 0000000..9736302 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/database/entities/Actuator.java @@ -0,0 +1,91 @@ +package net.miarma.contaminus.database.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; + +@Table("actuators") +public class Actuator { + + private int actuatorId; + private int deviceId; + private int status; + private long timestamp; + + public Actuator() {} + + public Actuator(Row row) { + this.actuatorId = row.getInteger("actuatorId"); + this.deviceId = row.getInteger("deviceId"); + this.status = row.getInteger("status"); + this.timestamp = row.getLong("timestamp"); + } + + public Actuator(int actuatorId, int deviceId, int status, long timestamp) { + super(); + this.actuatorId = actuatorId; + this.deviceId = deviceId; + this.status = status; + this.timestamp = timestamp; + } + + public int getActuatorId() { + return actuatorId; + } + + public void setActuatorId(int actuatorId) { + this.actuatorId = actuatorId; + } + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(actuatorId, deviceId, status, timestamp); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Actuator other = (Actuator) obj; + return actuatorId == other.actuatorId && deviceId == other.deviceId + && status == other.status && timestamp == other.timestamp; + } + + @Override + public String toString() { + return "Actuator [actuatorId=" + actuatorId + ", deviceId=" + deviceId + ", status=" + status + ", timestamp=" + + timestamp + "]"; + } + + + +} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/COValue.java b/backend/src/main/java/net/miarma/contaminus/database/entities/COValue.java new file mode 100644 index 0000000..26fcc02 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/database/entities/COValue.java @@ -0,0 +1,91 @@ +package net.miarma.contaminus.database.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; + +@Table("co_values") +public class COValue { + + private int valueId; + private int sensorId; + private float value; + private long timestamp; + + public COValue() {} + + public COValue(Row row) { + this.valueId = row.getInteger("valueId"); + this.sensorId = row.getInteger("sensorId"); + this.value = row.getFloat("value"); + this.timestamp = row.getLong("timestamp"); + } + + public COValue(int valueId, int sensorId, float value, long timestamp) { + super(); + this.valueId = valueId; + this.sensorId = sensorId; + this.value = value; + this.timestamp = timestamp; + } + + public int getValueId() { + return valueId; + } + + public void setValueId(int valueId) { + this.valueId = valueId; + } + + public int getSensorId() { + return sensorId; + } + + public void setSensorId(int sensorId) { + this.sensorId = sensorId; + } + + public float getValue() { + return value; + } + + public void setValue(float value) { + this.value = value; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(sensorId, timestamp, value, valueId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + COValue other = (COValue) obj; + return sensorId == other.sensorId + && Objects.equals(timestamp, other.timestamp) + && Float.floatToIntBits(value) == Float.floatToIntBits(other.value) && valueId == other.valueId; + } + + @Override + public String toString() { + return "COValue [valueId=" + valueId + ", sensorId=" + sensorId + ", value=" + value + ", timestamp=" + + timestamp + "]"; + } + + +} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/Device.java b/backend/src/main/java/net/miarma/contaminus/database/entities/Device.java new file mode 100644 index 0000000..db9f60e --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/database/entities/Device.java @@ -0,0 +1,81 @@ +package net.miarma.contaminus.database.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; + +@Table("devices") +public class Device { + + private int deviceId; + private int groupId; + private String deviceName; + + public Device() {} + + public Device(Row row) { + this.deviceId = row.getInteger("deviceId"); + this.groupId = row.getInteger("groupId"); + this.deviceName = row.getString("deviceName"); + } + + public Device(int deviceId, int groupId, String deviceName) { + super(); + this.deviceId = deviceId; + this.groupId = groupId; + this.deviceName = deviceName; + } + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + @Override + public int hashCode() { + return Objects.hash(deviceId, deviceName, groupId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Device other = (Device) obj; + return deviceId == other.deviceId + && Objects.equals(deviceName, other.deviceName) + && groupId == other.groupId; + } + + @Override + public String toString() { + return "Device [deviceId=" + deviceId + ", groupId=" + groupId + ", deviceName=" + deviceName + "]"; + } + + + +} + diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/GpsValue.java b/backend/src/main/java/net/miarma/contaminus/database/entities/GpsValue.java new file mode 100644 index 0000000..b0db81b --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/database/entities/GpsValue.java @@ -0,0 +1,103 @@ +package net.miarma.contaminus.database.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; + +@Table("gps_values") +public class GpsValue { + + private int valueId; + private int sensorId; + private float lat; + private float lon; + private long timestamp; + + public GpsValue() {} + + public GpsValue(Row row) { + this.valueId = row.getInteger("valueId"); + this.sensorId = row.getInteger("sensorId"); + this.lat = row.getFloat("lat"); + this.lon = row.getFloat("lon"); + this.timestamp = row.getLong("timestamp"); + } + + public GpsValue(int valueId, int sensorId, float lat, float lon, long timestamp) { + super(); + this.valueId = valueId; + this.sensorId = sensorId; + this.lat = lat; + this.lon = lon; + this.timestamp = timestamp; + } + + public int getValueId() { + return valueId; + } + + public void setValueId(int valueId) { + this.valueId = valueId; + } + + public int getSensorId() { + return sensorId; + } + + public void setSensorId(int sensorId) { + this.sensorId = sensorId; + } + + public float getLat() { + return lat; + } + + public void setLat(float lat) { + this.lat = lat; + } + + public float getLon() { + return lon; + } + + public void setLon(float lon) { + this.lon = lon; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(lat, lon, sensorId, timestamp, valueId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + GpsValue other = (GpsValue) obj; + return Float.floatToIntBits(lat) == Float.floatToIntBits(other.lat) + && Float.floatToIntBits(lon) == Float.floatToIntBits(other.lon) + && sensorId == other.sensorId && timestamp == other.timestamp && valueId == other.valueId; + } + + @Override + public String toString() { + return "GpsValue [valueId=" + valueId + ", sensorId=" + sensorId + ", lat=" + lat + ", lon=" + lon + + ", timestamp=" + timestamp + "]"; + } + + + +} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/Group.java b/backend/src/main/java/net/miarma/contaminus/database/entities/Group.java new file mode 100644 index 0000000..58f1e2a --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/database/entities/Group.java @@ -0,0 +1,67 @@ +package net.miarma.contaminus.database.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; + +@Table("groups") +public class Group { + + private int groupId; + private String groupName; + + public Group() {} + + public Group(Row row) { + this.groupId = row.getInteger("groupId"); + this.groupName = row.getString("groupName"); + } + + public Group(int groupId, String groupName) { + super(); + this.groupId = groupId; + this.groupName = groupName; + } + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + @Override + public int hashCode() { + return Objects.hash(groupId, groupName); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Group other = (Group) obj; + return groupId == other.groupId + && Objects.equals(groupName, other.groupName); + } + + @Override + public String toString() { + return "Group [groupId=" + groupId + ", groupName=" + groupName + "]"; + } + + +} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/Sensor.java b/backend/src/main/java/net/miarma/contaminus/database/entities/Sensor.java new file mode 100644 index 0000000..9000a20 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/database/entities/Sensor.java @@ -0,0 +1,112 @@ +package net.miarma.contaminus.database.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; + +@Table("sensors") +public class Sensor { + + private int sensorId; + private int deviceId; + private String sensorType; + private String unit; + private int status; + private long timestamp; + + public Sensor() {} + + public Sensor(Row row) { + this.sensorId = row.getInteger("sensorId"); + this.deviceId = row.getInteger("deviceId"); + this.sensorType = row.getString("sensorType"); + this.unit = row.getString("unit"); + this.status = row.getInteger("status"); + this.timestamp = row.getLong("timestamp"); + } + + public Sensor(int sensorId, int deviceId, String sensorType, String unit, int status, long timestamp) { + super(); + this.sensorId = sensorId; + this.deviceId = deviceId; + this.sensorType = sensorType; + this.unit = unit; + this.status = status; + this.timestamp = timestamp; + } + + public int getSensorId() { + return sensorId; + } + + public void setSensorId(int sensorId) { + this.sensorId = sensorId; + } + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public String getSensorType() { + return sensorType; + } + + public void setSensorType(String sensorType) { + this.sensorType = sensorType; + } + + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(deviceId, sensorId, sensorType, status, timestamp, unit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Sensor other = (Sensor) obj; + return deviceId == other.deviceId && sensorId == other.sensorId && Objects.equals(sensorType, other.sensorType) + && status == other.status && timestamp == other.timestamp && Objects.equals(unit, other.unit); + } + + @Override + public String toString() { + return "Sensor [sensorId=" + sensorId + ", deviceId=" + deviceId + ", sensorType=" + sensorType + ", unit=" + + unit + ", status=" + status + ", timestamp=" + timestamp + "]"; + } + + +} diff --git a/backend/src/main/java/net/miarma/contaminus/database/entities/WeatherValue.java b/backend/src/main/java/net/miarma/contaminus/database/entities/WeatherValue.java new file mode 100644 index 0000000..e69f485 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/database/entities/WeatherValue.java @@ -0,0 +1,103 @@ +package net.miarma.contaminus.database.entities; + +import java.util.Objects; + +import io.vertx.sqlclient.Row; +import net.miarma.contaminus.common.Table; + +@Table("weather_values") +public class WeatherValue { + + private int valueId; + private int sensorId; + private float temperature; + private float humidity; + private long timestamp; + + public WeatherValue() {} + + public WeatherValue(Row row) { + this.valueId = row.getInteger("valueId"); + this.sensorId = row.getInteger("sensorId"); + this.temperature = row.getFloat("temperature"); + this.humidity = row.getFloat("humidity"); + this.timestamp = row.getLong("timestamp"); + } + + public WeatherValue(int valueId, int sensorId, float temperature, float humidity, long timestamp) { + super(); + this.valueId = valueId; + this.sensorId = sensorId; + this.temperature = temperature; + this.humidity = humidity; + this.timestamp = timestamp; + } + + public int getValueId() { + return valueId; + } + + public void setValueId(int valueId) { + this.valueId = valueId; + } + + public int getSensorId() { + return sensorId; + } + + public void setSensorId(int sensorId) { + this.sensorId = sensorId; + } + + public float getTemperature() { + return temperature; + } + + public void setTemperature(float temperature) { + this.temperature = temperature; + } + + public float getHumidity() { + return humidity; + } + + public void setHumidity(float humidity) { + this.humidity = humidity; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + @Override + public int hashCode() { + return Objects.hash(humidity, sensorId, temperature, timestamp, valueId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + WeatherValue other = (WeatherValue) obj; + return Float.floatToIntBits(humidity) == Float.floatToIntBits(other.humidity) && sensorId == other.sensorId + && Float.floatToIntBits(temperature) == Float.floatToIntBits(other.temperature) + && timestamp == other.timestamp && valueId == other.valueId; + } + + @Override + public String toString() { + return "WeatherValue [valueId=" + valueId + ", sensorId=" + sensorId + ", temperature=" + temperature + + ", humidity=" + humidity + ", timestamp=" + timestamp + "]"; + } + + + +} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/server/ApiVerticle.java b/backend/src/main/java/net/miarma/contaminus/server/ApiVerticle.java deleted file mode 100644 index 596b5a4..0000000 --- a/backend/src/main/java/net/miarma/contaminus/server/ApiVerticle.java +++ /dev/null @@ -1,403 +0,0 @@ -package net.miarma.contaminus.server; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import io.vertx.core.AbstractVerticle; -import io.vertx.core.Promise; -import io.vertx.core.eventbus.Message; -import io.vertx.core.http.HttpMethod; -import io.vertx.core.json.JsonArray; -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 net.miarma.contaminus.common.Constants; -import net.miarma.contaminus.common.Host; -import net.miarma.contaminus.database.QueryBuilder; - -public class ApiVerticle extends AbstractVerticle { - - @Override - public void start(Promise startPromise) { - Constants.LOGGER.info("🟒 Iniciando ApiVerticle..."); - Router router = Router.router(vertx); - - Set allowedMethods = new HashSet<>( - Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); // Por ejemplo - Set allowedHeaders = new HashSet<>(Arrays.asList("Content-Type", "Authorization")); - - router.route().handler(CorsHandler.create() - .allowCredentials(true) - .allowedHeaders(allowedHeaders) - .allowedMethods(allowedMethods)); - router.route().handler(BodyHandler.create()); - - // Group Routes - router.route(HttpMethod.GET, Constants.GET_GROUPS).handler(this::getGroupsHandler); - router.route(HttpMethod.GET, Constants.GET_GROUP_BY_ID).handler(this::getGroupByIdHandler); - router.route(HttpMethod.GET, Constants.GET_GROUP_DEVICES).handler(this::getGroupDevicesHandler); - router.route(HttpMethod.POST, Constants.POST_GROUPS).handler(this::postGroupHandler); - router.route(HttpMethod.PUT, Constants.PUT_GROUP_BY_ID).handler(this::putGroupByIdHandler); - - // Device Routes - router.route(HttpMethod.GET, Constants.GET_DEVICES).handler(this::getDevicesHandler); - router.route(HttpMethod.GET, Constants.GET_DEVICE_BY_ID).handler(this::getDeviceByIdHandler); - router.route(HttpMethod.GET, Constants.GET_DEVICE_SENSORS).handler(this::getDeviceSensorsHandler); - router.route(HttpMethod.GET, Constants.GET_DEVICE_ACTUATORS).handler(this::getDeviceActuatorsHandler); - router.route(HttpMethod.GET, Constants.GET_DEVICE_LATEST_VALUES).handler(this::getDeviceLatestValuesHandler); - router.route(HttpMethod.POST, Constants.POST_DEVICES).handler(this::postDeviceHandler); - router.route(HttpMethod.PUT, Constants.PUT_DEVICE_BY_ID).handler(this::putDeviceByIdHandler); - router.route(HttpMethod.GET, Constants.GET_DEVICE_POLLUTION_MAP).handler(this::getPollutionMapHandler); - router.route(HttpMethod.GET, Constants.GET_DEVICE_HISTORY).handler(this::getDeviceHistoryHandler); - - // Sensor Routes - router.route(HttpMethod.GET, Constants.GET_SENSORS).handler(this::getSensorsHandler); - router.route(HttpMethod.GET, Constants.GET_SENSOR_BY_ID).handler(this::getSensorByIdHandler); - router.route(HttpMethod.GET, Constants.GET_SENSOR_VALUES).handler(this::getSensorValuesHandler); - router.route(HttpMethod.POST, Constants.POST_SENSORS).handler(this::postSensorHandler); - router.route(HttpMethod.PUT, Constants.PUT_SENSOR_BY_ID).handler(this::putSensorByIdHandler); - - // Actuator Routes - router.route(HttpMethod.GET, Constants.GET_ACTUATORS).handler(this::getActuatorsHandler); - router.route(HttpMethod.GET, Constants.GET_ACTUATOR_BY_ID).handler(this::getActuatorByIdHandler); - router.route(HttpMethod.POST, Constants.POST_ACTUATORS).handler(this::postActuatorHandler); - router.route(HttpMethod.PUT, Constants.PUT_ACTUATOR_BY_ID).handler(this::putActuatorByIdHandler); - - vertx.createHttpServer() - .requestHandler(router) - .listen( - Host.getApiPort(), - Host.getHost(), - result -> { - if (result.succeeded()) { - Constants.LOGGER.info(String.format( - "πŸ“‘ ApiVerticle desplegado. (http://%s:%d)", Host.getHost(), Host.getApiPort() - )); - startPromise.complete(); - } else { - Constants.LOGGER.error("❌ Error al desplegar ApiVerticle", result.cause()); - startPromise.fail(result.cause()); - } - }); - } - - private void sendQuery(String query, RoutingContext context) { - vertx.eventBus().request("db.query", query, req -> { - if (req.succeeded()) { - Message msg = req.result(); - JsonArray jsonArray = new JsonArray(msg.body().toString()); - context.json(jsonArray); - } else { - context.fail(500, req.cause()); - } - }); - } - - - // Group Handlers - private void getGroupsHandler(RoutingContext context) { - String query = QueryBuilder.select("*").from("groups").build(); - sendQuery(query, context); - } - - private void getGroupByIdHandler(RoutingContext context) { - String groupId = context.request().getParam("groupId"); - String query = QueryBuilder - .select("*") - .from("groups") - .where("groupId = ?", groupId) - .build(); - sendQuery(query, context); - } - - private void getGroupDevicesHandler(RoutingContext context) { - String groupId = context.request().getParam("groupId"); - String query = QueryBuilder - .select("*") - .from("devices") - .where("groupId = ?", groupId) - .build(); - sendQuery(query, context); - } - - private void postGroupHandler(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - - if(body == null) { - context.fail(400, new IllegalArgumentException("Bad request")); - return; - } - - String groupName = body.getString("groupName"); - - String query = QueryBuilder - .insert("groups", "groupName") - .values(groupName) - .build(); - - sendQuery(query, context); - } - - private void putGroupByIdHandler(RoutingContext context) { - String groupId = context.request().getParam("groupId"); - JsonObject body = context.body().asJsonObject(); - - if(body == null) { - context.fail(400, new IllegalArgumentException("Bad request")); - return; - } - - String groupName = body.getString("groupName"); - - String query = QueryBuilder - .update("groups") - .set("groupName", groupName) - .where("groupId = ?", groupId) - .build(); - - sendQuery(query, context); - } - - // Device Handlers - private void getDevicesHandler(RoutingContext context) { - String query = QueryBuilder.select("*").from("devices").build(); - sendQuery(query, context); - } - - private void getDeviceByIdHandler(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - String query = QueryBuilder - .select("*") - .from("devices") - .where("deviceId = ?", deviceId) - .build(); - sendQuery(query, context); - } - - private void getDeviceSensorsHandler(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - String query = QueryBuilder - .select("*") - .from("sensors") - .where("deviceId = ?", deviceId) - .build(); - sendQuery(query, context); - } - - private void getDeviceActuatorsHandler(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - String query = QueryBuilder - .select("*") - .from("actuators") - .where("deviceId = ?", deviceId) - .build(); - sendQuery(query, context); - } - - private void getDeviceLatestValuesHandler(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - String query = QueryBuilder - .select("*") - .from("v_latest_values") - .where("deviceId = ?", deviceId) - .build(); - sendQuery(query, context); - } - - private void postDeviceHandler(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - - if(body == null) { - context.fail(400, new IllegalArgumentException("Bad request")); - return; - } - - Integer groupId = body.getInteger("groupId"); - String deviceName = body.getString("groupName"); - - String query = QueryBuilder - .insert("devices", "groupId", "deviceName") - .values(groupId, deviceName) - .build(); - - sendQuery(query, context); - } - - private void putDeviceByIdHandler(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - JsonObject body = context.body().asJsonObject(); - - if(body == null) { - context.fail(400, new IllegalArgumentException("Bad request")); - return; - } - - Integer groupId = body.getInteger("groupId"); - String deviceName = body.getString("deviceName"); - - String query = QueryBuilder - .update("devices") - .set("groupId", groupId) - .set("deviceName", deviceName) - .where("deviceId = ?", deviceId) - .build(); - - sendQuery(query, context); - } - - private void getPollutionMapHandler(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - String query = QueryBuilder - .select("*") - .from("v_pollution_map") - .where("deviceId = ?", deviceId) - .build(); - sendQuery(query, context); - } - - private void getDeviceHistoryHandler(RoutingContext context) { - String deviceId = context.request().getParam("deviceId"); - String query = QueryBuilder - .select("*") - .from("v_sensor_history_by_device") - .where("deviceId = ?", deviceId) - .build(); - sendQuery(query, context); - } - - // Sensor Handlers - private void getSensorsHandler(RoutingContext context) { - String query = QueryBuilder.select("*").from("sensors").build(); - sendQuery(query, context); - } - - private void getSensorByIdHandler(RoutingContext context) { - String sensorId = context.request().getParam("sensorId"); - String query = QueryBuilder - .select("*") - .from("sensors") - .where("sensorId = ?", sensorId) - .build(); - sendQuery(query, context); - } - - private void getSensorValuesHandler(RoutingContext context) { - String sensorId = context.request().getParam("sensorId"); - String query = QueryBuilder - .select("*") - .from("v_sensor_values") - .where("sensorId = ?", sensorId) - .build(); - sendQuery(query, context); - } - - private void postSensorHandler(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - - if(body == null) { - context.fail(400, new IllegalArgumentException("Bad request")); - return; - } - - Integer deviceId = body.getInteger("deviceId"); - String sensorType = body.getString("sensorType"); - String unit = body.getString("unit"); - Integer status = body.getInteger("status"); - - String query = QueryBuilder - .insert("sensors", "deviceId", "sensorType", "unit", "status") - .values(deviceId, sensorType, unit, status) - .build(); - - sendQuery(query, context); - } - - private void putSensorByIdHandler(RoutingContext context) { - String sensorId = context.request().getParam("sensorId"); - JsonObject body = context.body().asJsonObject(); - - if(body == null) { - context.fail(400, new IllegalArgumentException("Bad request")); - return; - } - - Integer deviceId = body.getInteger("deviceId"); - String sensorType = body.getString("sensorType"); - String unit = body.getString("unit"); - Integer status = body.getInteger("status"); - - String query = QueryBuilder - .update("sensors") - .set("deviceId", deviceId) - .set("sensorType", sensorType) - .set("unit", unit) - .set("status", status) - .where("sensorId = ?", sensorId) - .build(); - - sendQuery(query, context); - } - - // Actuator Handlers - private void getActuatorsHandler(RoutingContext context) { - String query = QueryBuilder.select("*").from("actuators").build(); - sendQuery(query, context); - } - - private void getActuatorByIdHandler(RoutingContext context) { - String actuatorId = context.request().getParam("actuatorId"); - - String query = QueryBuilder - .select("*") - .from("actuators") - .where("actuatorId = ?", actuatorId) - .build(); - - sendQuery(query, context); - } - - private void postActuatorHandler(RoutingContext context) { - JsonObject body = context.body().asJsonObject(); - - if(body == null) { - context.fail(400, new IllegalArgumentException("Bad request")); - return; - } - - Integer deviceId = body.getInteger("deviceId"); - Integer status = body.getInteger("status"); - - String query = QueryBuilder - .insert("actuators", "deviceId", "status") - .values(deviceId, status) - .build(); - - sendQuery(query, context); - } - - private void putActuatorByIdHandler(RoutingContext context) { - String actuatorId = context.request().getParam("actuatorId"); - JsonObject body = context.body().asJsonObject(); - - if(body == null) { - context.fail(400, new IllegalArgumentException("Bad request")); - return; - } - - Integer deviceId = body.getInteger("deviceId"); - Integer status = body.getInteger("status"); - - String query = QueryBuilder - .update("actuators") - .set("deviceId", deviceId) - .set("status", status) - .where("actuatorId = ?", actuatorId) - .build(); - - sendQuery(query, context); - } - -} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/server/DataLayerAPIVerticle.java b/backend/src/main/java/net/miarma/contaminus/server/DataLayerAPIVerticle.java new file mode 100644 index 0000000..35e641b --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/server/DataLayerAPIVerticle.java @@ -0,0 +1,145 @@ +package net.miarma.contaminus.server; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +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.JDBCConnectOptions; +import io.vertx.jdbcclient.JDBCPool; +import io.vertx.sqlclient.PoolOptions; +import net.miarma.contaminus.common.ConfigManager; +import net.miarma.contaminus.common.Constants; +import net.miarma.contaminus.database.DatabaseManager; + +@SuppressWarnings("unused") +public class DataLayerAPIVerticle extends AbstractVerticle { + private JDBCPool pool; + private DatabaseManager dbManager; + private ConfigManager configManager; + + public DataLayerAPIVerticle(JDBCPool pool) { + this.pool = pool; + this.configManager = ConfigManager.getInstance(); + } + + @Override + public void start(Promise startPromise) { + Constants.LOGGER.info("πŸ“‘ Iniciando DataLayerAPIVerticle..."); + dbManager = DatabaseManager.getInstance(pool); + + Router router = Router.router(vertx); + Set allowedMethods = new HashSet<>( + Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); // Por ejemplo + Set allowedHeaders = new HashSet<>(Arrays.asList("Content-Type", "Authorization")); + + router.route().handler(CorsHandler.create() + .allowCredentials(true) + .allowedHeaders(allowedHeaders) + .allowedMethods(allowedMethods)); + router.route().handler(BodyHandler.create()); + + // 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); + + vertx.createHttpServer() + .requestHandler(router) + .listen(configManager.getDataApiPort(), configManager.getHost()); + + startPromise.complete(); + } + + private void getAllGroups(RoutingContext context) { + context.response().end("TODO"); + } + + private void getGroupById(RoutingContext context) { + context.response().end("TODO"); + } + + private void addGroup(RoutingContext context) { + context.response().end("TODO"); + } + + private void updateGroup(RoutingContext context) { + context.response().end("TODO"); + } + + private void getAllDevices(RoutingContext context) { + context.response().end("TODO"); + } + + private void getDeviceById(RoutingContext context) { + context.response().end("TODO"); + } + + private void addDevice(RoutingContext context) { + context.response().end("TODO"); + } + + private void updateDevice(RoutingContext context) { + context.response().end("TODO"); + } + + private void getAllSensors(RoutingContext context) { + context.response().end("TODO"); + } + + private void getSensorById(RoutingContext context) { + context.response().end("TODO"); + } + + private void addSensor(RoutingContext context) { + context.response().end("TODO"); + } + + private void updateSensor(RoutingContext context) { + context.response().end("TODO"); + } + + private void getAllActuators(RoutingContext context) { + context.response().end("TODO"); + } + + private void getActuatorById(RoutingContext context) { + context.response().end("TODO"); + } + + private void addActuator(RoutingContext context) { + context.response().end("TODO"); + } + + private void updateActuator(RoutingContext context) { + context.response().end("TODO"); + } + +} diff --git a/backend/src/main/java/net/miarma/contaminus/server/DatabaseVerticle.java b/backend/src/main/java/net/miarma/contaminus/server/DatabaseVerticle.java deleted file mode 100644 index bf56561..0000000 --- a/backend/src/main/java/net/miarma/contaminus/server/DatabaseVerticle.java +++ /dev/null @@ -1,120 +0,0 @@ -package net.miarma.contaminus.server; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import io.vertx.core.AbstractVerticle; -import io.vertx.core.Promise; -import io.vertx.core.eventbus.EventBus; -import io.vertx.core.eventbus.Message; -import io.vertx.core.json.JsonObject; -import io.vertx.jdbcclient.JDBCPool; -import io.vertx.sqlclient.Row; -import net.miarma.contaminus.common.Constants; -import net.miarma.contaminus.common.LocalDateTimeSerializer; -import net.miarma.contaminus.database.DatabaseManager; - -public class DatabaseVerticle extends AbstractVerticle { - private JDBCPool pool; - private EventBus eventBus; - private Gson gson = new GsonBuilder() - .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer()) - .create(); - - - @SuppressWarnings("unused") - @Override - public void start(Promise startPromise) { - Constants.LOGGER.info("🟒 Iniciando DatabaseVerticle..."); - - DatabaseManager dbManager = new DatabaseManager(vertx); - pool = dbManager.getPool(); - eventBus = vertx.eventBus(); - - pool.query("SELECT 1") - .execute() - .onSuccess(_res -> { - Constants.LOGGER.info("βœ… Database connection ok"); - Constants.LOGGER.info("πŸ“‘ DatabaseVerticle desplegado"); - startPromise.complete(); - }) - .onFailure(err -> { - Constants.LOGGER.error("❌ Database connection failed"); - Constants.LOGGER.error("❌ Error al desplegar DatabaseVerticle", err); - startPromise.fail(err); - }); - - eventBus.consumer("db.query", this::handleDatabaseQuery); - } - - private void handleDatabaseQuery(Message msg) { - String query = msg.body(); - Constants.LOGGER.info("πŸ“₯ Query: " + query); - - if(query == null || query.isEmpty()) { - msg.fail(400, "Empty query"); - return; - } - - if(query.startsWith("SELECT")) { - handleSelectQuery(query, msg); - } else if(query.startsWith("INSERT")) { - handleInsertQuery(query, msg); - } else if(query.startsWith("UPDATE")) { - handleUpdateQuery(query, msg); - } else { - msg.fail(400, "Invalid operation"); - } - } - - private void handleSelectQuery(String query, Message msg) { - pool.query(query).execute() - .onSuccess(res -> { - List> rowsList = new ArrayList<>(); - - for (Row row : res) { - Map rowMap = new HashMap<>(); - for (int i = 0; i < row.size(); i++) { - String columnName = res.columnsNames().get(i); - Object columnValue = row.getValue(i); - rowMap.put(columnName, columnValue); - } - rowsList.add(rowMap); - } - - String jsonResponse = gson.toJson(rowsList); - msg.reply(jsonResponse); - }) - .onFailure(err -> msg.fail(500, err.getMessage())); - } - - @SuppressWarnings("unused") - private void handleInsertQuery(String query, Message msg) { - pool.query(query).execute() - .onSuccess(_res -> { - JsonObject response = new JsonObject(); - response.put("status", "success"); - String jsonResponse = gson.toJson(response); - msg.reply(jsonResponse); - }) - .onFailure(err -> msg.fail(500, err.getMessage())); - } - - @SuppressWarnings("unused") - private void handleUpdateQuery(String query, Message msg) { - pool.query(query).execute() - .onSuccess(_res -> { - JsonObject response = new JsonObject(); - response.put("status", "updated"); - String jsonResponse = gson.toJson(response); - msg.reply(jsonResponse); - }) - .onFailure(err -> msg.fail(500, err.getMessage())); - } -} diff --git a/backend/src/main/java/net/miarma/contaminus/server/HttpServerVerticle.java b/backend/src/main/java/net/miarma/contaminus/server/HttpServerVerticle.java deleted file mode 100644 index 4be8d38..0000000 --- a/backend/src/main/java/net/miarma/contaminus/server/HttpServerVerticle.java +++ /dev/null @@ -1,39 +0,0 @@ -package net.miarma.contaminus.server; - -import io.vertx.core.AbstractVerticle; -import io.vertx.ext.web.Router; -import io.vertx.ext.web.handler.StaticHandler; -import net.miarma.contaminus.common.Constants; -import net.miarma.contaminus.common.Host; - -public class HttpServerVerticle extends AbstractVerticle { - - @Override - public void start() { - Constants.LOGGER.info("🟒 Iniciando HttpServerVerticle..."); - - Router router = Router.router(vertx); - - router.route("/*") - .handler( - StaticHandler.create("webroot") - .setDefaultContentEncoding("UTF-8") - ); - - router.route("/dashboard/*").handler(ctx -> { - ctx.reroute("/index.html"); - }); - - vertx.createHttpServer().requestHandler(router).listen( - Host.getWebserverPort(), Host.getHost(), result -> { - if (result.succeeded()) { - Constants.LOGGER.info(String.format("πŸ“‘ HttpServerVerticle desplegado. (http://%s:%d)", - Host.getHost(), Host.getWebserverPort()) - ); - } else { - Constants.LOGGER.error("❌ Error al desplegar HttpServerVerticle", result.cause()); - } - } - ); - } -} diff --git a/backend/src/main/java/net/miarma/contaminus/server/LogicLayerAPIVerticle.java b/backend/src/main/java/net/miarma/contaminus/server/LogicLayerAPIVerticle.java new file mode 100644 index 0000000..57ccf98 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/server/LogicLayerAPIVerticle.java @@ -0,0 +1,88 @@ +package net.miarma.contaminus.server; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Promise; +import io.vertx.core.http.HttpMethod; +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 net.miarma.contaminus.common.ConfigManager; +import net.miarma.contaminus.common.Constants; + +public class LogicLayerAPIVerticle extends AbstractVerticle { + private ConfigManager configManager; + + public LogicLayerAPIVerticle() { + this.configManager = ConfigManager.getInstance(); + } + + @Override + public void start(Promise startPromise) { + Constants.LOGGER.info("πŸ“‘ Iniciando LogicApiVerticle..."); + + Router router = Router.router(vertx); + Set allowedMethods = new HashSet<>( + Arrays.asList(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.OPTIONS)); // Por ejemplo + Set allowedHeaders = new HashSet<>(Arrays.asList("Content-Type", "Authorization")); + + router.route().handler(CorsHandler.create() + .allowCredentials(true) + .allowedHeaders(allowedHeaders) + .allowedMethods(allowedMethods)); + router.route().handler(BodyHandler.create()); + + // Group Routes + router.route(HttpMethod.GET, Constants.GET_GROUP_DEVICES).handler(this::getGroupDevices); + + // Device Routes + 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); + + // Sensor Routes + 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) { + context.response().end("TODO"); + } + + private void getDeviceSensors(RoutingContext context) { + context.response().end("TODO"); + } + + private void getDeviceActuators(RoutingContext context) { + context.response().end("TODO"); + } + + private void getDeviceLatestValues(RoutingContext context) { + context.response().end("TODO"); + } + + private void getDevicePollutionMap(RoutingContext context) { + context.response().end("TODO"); + } + + private void getDeviceHistory(RoutingContext context) { + context.response().end("TODO"); + } + + private void getSensorValues(RoutingContext context) { + context.response().end("TODO"); + } + +} \ No newline at end of file diff --git a/backend/src/main/java/net/miarma/contaminus/server/MainVerticle.java b/backend/src/main/java/net/miarma/contaminus/server/MainVerticle.java index a520ae6..831e8dd 100644 --- a/backend/src/main/java/net/miarma/contaminus/server/MainVerticle.java +++ b/backend/src/main/java/net/miarma/contaminus/server/MainVerticle.java @@ -1,39 +1,133 @@ package net.miarma.contaminus.server; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; + +import io.vertx.core.json.JsonObject; +import io.vertx.jdbcclient.JDBCPool; import io.vertx.core.AbstractVerticle; import io.vertx.core.DeploymentOptions; +import io.vertx.core.Launcher; import io.vertx.core.Promise; import io.vertx.core.ThreadingModel; +import net.miarma.contaminus.common.ConfigManager; +import net.miarma.contaminus.common.Constants; public class MainVerticle extends AbstractVerticle { + private ConfigManager configManager; + private JDBCPool pool; + + public static void main(String[] args) { + Launcher.executeCommand("run", MainVerticle.class.getName()); + } - @Override - public void start(Promise startPromise) { - final DeploymentOptions options = new DeploymentOptions(); - options.setThreadingModel(ThreadingModel.WORKER); - - String enabledVerticles = System.getProperty("vertx.options", ""); - - if (enabledVerticles.contains("db")) { - getVertx().deployVerticle(new DatabaseVerticle(), options); - } - if (enabledVerticles.contains("api")) { - getVertx().deployVerticle(new ApiVerticle(), options); - } - if (enabledVerticles.contains("http")) { - getVertx().deployVerticle(new HttpServerVerticle()); - } - } - - @Override - public void stop(Promise stopPromise) throws Exception { - getVertx().deploymentIDs() - .forEach(v -> getVertx().undeploy(v)); - } - - public static void main(String[] args) { - System.setProperty("vertx.options", String.join(",", args)); - io.vertx.core.Launcher.executeCommand("run", MainVerticle.class.getName()); - } - -} \ No newline at end of file + @SuppressWarnings("deprecation") + private void init() { + 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); + + pool = JDBCPool.pool(vertx, dbConfig); + + initializeDirectories(); + copyDefaultConfig(); + } + + private void initializeDirectories() { + File baseDir = new File(this.configManager.getBaseDir()); + if (!baseDir.exists()) { + baseDir.mkdirs(); + } + } + + private void copyDefaultConfig() { + File configFile = new File(configManager.getConfigFile().getAbsolutePath()); + if (!configFile.exists()) { + try (InputStream in = MainVerticle.class.getClassLoader().getResourceAsStream("default.properties")) { + if (in != null) { + Files.copy(in, configFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } else { + Constants.LOGGER.error("πŸ”΄ Default config file not found in resources"); + } + } catch (IOException e) { + Constants.LOGGER.error("πŸ”΄ Failed to copy default config file", e); + } + } + } + + @Override + public void start(Promise startPromise) { + try { + System.setProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager"); + init(); + pool.query("SELECT 1").execute(ar -> { + if (ar.succeeded()) { + Constants.LOGGER.info("🟒 Connected to DB"); + deployVerticles(startPromise); + } else { + Constants.LOGGER.error("πŸ”΄ Failed to connect to DB: " + ar.cause()); + startPromise.fail(ar.cause()); + } + }); + } catch (Exception e) { + System.err.println("πŸ”΄ Error starting the application: " + e); + startPromise.fail(e); + } + } + + private void deployVerticles(Promise startPromise) { + final DeploymentOptions options = new DeploymentOptions(); + options.setThreadingModel(ThreadingModel.WORKER); + + vertx.deployVerticle(new DataLayerAPIVerticle(pool), options, result -> { + if (result.succeeded()) { + Constants.LOGGER.info("🟒 DatabaseVerticle desplegado"); + Constants.LOGGER.info("\tπŸ”— API URL: " + configManager.getHost() + + ":" + configManager.getDataApiPort()); + } else { + Constants.LOGGER.error("πŸ”΄ Error deploying DataLayerAPIVerticle: " + result.cause()); + } + }); + + vertx.deployVerticle(new LogicLayerAPIVerticle(), options, result -> { + if (result.succeeded()) { + Constants.LOGGER.info("🟒 LogicLayerAPIVerticle desplegado"); + Constants.LOGGER.info("\tπŸ”— API URL: " + configManager.getHost() + + ":" + configManager.getLogicApiPort()); + } else { + Constants.LOGGER.error("πŸ”΄ Error deploying LogicLayerAPIVerticle: " + result.cause()); + } + }); + + vertx.deployVerticle(new WebServerVerticle(), result -> { + if (result.succeeded()) { + Constants.LOGGER.info("🟒 WebServerVerticle desplegado"); + Constants.LOGGER.info("\tπŸ”— WEB SERVER URL: " + configManager.getHost() + + ":" + configManager.getWebserverPort()); + } else { + Constants.LOGGER.error("πŸ”΄ Error deploying WebServerVerticle: " + result.cause()); + } + }); + + startPromise.complete(); + } + + @Override + public void stop(Promise stopPromise) throws Exception { + getVertx().deploymentIDs() + .forEach(v -> getVertx().undeploy(v)); + } + +} diff --git a/backend/src/main/java/net/miarma/contaminus/server/WebServerVerticle.java b/backend/src/main/java/net/miarma/contaminus/server/WebServerVerticle.java new file mode 100644 index 0000000..b302ac4 --- /dev/null +++ b/backend/src/main/java/net/miarma/contaminus/server/WebServerVerticle.java @@ -0,0 +1,39 @@ +package net.miarma.contaminus.server; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Promise; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.handler.StaticHandler; +import net.miarma.contaminus.common.ConfigManager; +import net.miarma.contaminus.common.Constants; + +public class WebServerVerticle extends AbstractVerticle { + private ConfigManager configManager; + + public WebServerVerticle() { + configManager = ConfigManager.getInstance(); + } + + @Override + public void start(Promise startPromise) { + Constants.LOGGER.info("πŸ“‘ Iniciando WebServerVerticle..."); + + Router router = Router.router(vertx); + + router.route("/*") + .handler( + StaticHandler.create("webroot") + .setDefaultContentEncoding("UTF-8") + ); + + router.route("/dashboard/*").handler(ctx -> { + ctx.reroute("/index.html"); + }); + + vertx.createHttpServer() + .requestHandler(router) + .listen(configManager.getWebserverPort(), configManager.getHost()); + + startPromise.complete(); + } +} diff --git a/backend/src/main/resources/default.properties b/backend/src/main/resources/default.properties index 0b63564..e0824ae 100644 --- a/backend/src/main/resources/default.properties +++ b/backend/src/main/resources/default.properties @@ -1,5 +1,5 @@ # DB Configuration -db.protocol=jdbc:mariadb: +db.protocol=jdbc:mariadb db.host=localhost db.port=3306 db.name=dad @@ -7,7 +7,8 @@ db.user=root db.pwd=root dp.poolSize=5 -# Server Configuration +# HTTP Server Configuration inet.host=localhost webserver.port=8080 -api.port=8081 +data-api.port=8081 +logic-api.port=8082 \ No newline at end of file diff --git a/backend/src/main/resources/webroot/config/settings.json b/backend/src/main/resources/webroot/config/settings.json index 58754ca..9570f6a 100644 --- a/backend/src/main/resources/webroot/config/settings.json +++ b/backend/src/main/resources/webroot/config/settings.json @@ -7,7 +7,7 @@ }, "appConfig": { "endpoints": { - "BASE_URL": "http://localhost:8081/api/v1", + "BASE_URL": "http://localhost:3001/api/v1", "GET_GROUPS": "/groups", "GET_GROUP_BY_ID": "/groups/{0}", "GET_GROUP_DEVICES": "/groups/{0}/devices",