+ * The pattern is defined as "yyyy-MM-dd'T'HH:mm:ss.SSS", where: + * - "yyyy" represents the year using four digits + * - "MM" represents the month using two digits + * - "dd" represents the day using two digits + * - "T" is a literal 'T' character, used to separate the date and time + * - "HH" represents the hour using two digits in the 24-hour format + * - "mm" represents the minute using two digits + * - "ss" represents the second using two digits + * - "SSS" represents the milliseconds using three digits + *
+ * This pattern is commonly used in JSON APIs for representing Instant objects in a consistent manner. + * It can be used to format Instant objects into strings or parse strings into Instant objects. + *
+ * Example usage: + *
{@code + * String instantString = "2022-12-31T23:59:59.999"; + * + * DateTimeFormatter formatter = DateTimeFormatter.ofPattern(INSTANT_JSON_PATTERN); + * Instant instant = Instant.parse(instantString, formatter); + * + * String formattedInstant = formatter.format(instant); + * System.out.println(formattedInstant); + * }+ */ + String INSTANT_JSON_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS"; +} diff --git a/src/main/java/de/app/fivegla/controller/DeviceMeasurementController.java b/src/main/java/de/app/fivegla/controller/DeviceMeasurementController.java index f8fd80be..9a52788d 100644 --- a/src/main/java/de/app/fivegla/controller/DeviceMeasurementController.java +++ b/src/main/java/de/app/fivegla/controller/DeviceMeasurementController.java @@ -8,6 +8,7 @@ import de.app.fivegla.controller.dto.request.SentekDataLoggingRequest; import de.app.fivegla.controller.dto.request.WeenatDataLoggingRequest; import de.app.fivegla.controller.security.SecuredApiAccess; +import de.app.fivegla.fiware.DeviceIntegrationService; import de.app.fivegla.integration.agvolution.AgvolutionFiwareIntegrationServiceWrapper; import de.app.fivegla.integration.agvolution.AgvolutionSensorIntegrationService; import de.app.fivegla.integration.sentek.SentekFiwareIntegrationServiceWrapper; @@ -41,18 +42,21 @@ public class DeviceMeasurementController implements SecuredApiAccess { private final AgvolutionSensorIntegrationService agvolutionSensorIntegrationService; private final AgvolutionFiwareIntegrationServiceWrapper agvolutionFiwareIntegrationServiceWrapper; + private final DeviceIntegrationService deviceIntegrationService; + public DeviceMeasurementController(SentekSensorIntegrationService sentekSensorIntegrationService, SentekFiwareIntegrationServiceWrapper sentekFiwareIntegrationServiceWrapper, WeenatPlotIntegrationService weenatPlotIntegrationService, WeenatFiwareIntegrationServiceWrapper weenatFiwareIntegrationServiceWrapper, AgvolutionSensorIntegrationService agvolutionSensorIntegrationService, - AgvolutionFiwareIntegrationServiceWrapper agvolutionFiwareIntegrationServiceWrapper) { + AgvolutionFiwareIntegrationServiceWrapper agvolutionFiwareIntegrationServiceWrapper, DeviceIntegrationService deviceIntegrationService) { this.sentekSensorIntegrationService = sentekSensorIntegrationService; this.sentekFiwareIntegrationServiceWrapper = sentekFiwareIntegrationServiceWrapper; this.weenatPlotIntegrationService = weenatPlotIntegrationService; this.weenatFiwareIntegrationServiceWrapper = weenatFiwareIntegrationServiceWrapper; this.agvolutionSensorIntegrationService = agvolutionSensorIntegrationService; this.agvolutionFiwareIntegrationServiceWrapper = agvolutionFiwareIntegrationServiceWrapper; + this.deviceIntegrationService = deviceIntegrationService; } /** @@ -83,7 +87,15 @@ public ResponseEntity
+ * This class is annotated with the Lombok's @Getter and @Setter annotations, + * which generate getters and setters for the private fields automatically. + * The class is also annotated with @Schema which can be used for generating + * documentation for API endpoints using Swagger or other similar frameworks. + *
+ * An instance of this class contains information about the time and value of + * a specific data point in a time series. The time is represented as an + * Instant object using the UTC timezone. The value is a Double representing + * the numeric value associated with the time. + *
+ * The time is formatted using the ISO 8601 standard date and time format, + * with milliseconds precision, and the UTC timezone. + *
+ * Example usage: + *
+ * TimeSeriesValue value = new TimeSeriesValue();
+ * value.setTime(Instant.now());
+ * value.setValue(42.0);
+ */
@Getter
@Setter
+@Schema(description = "Represents a value for a specific time in a time series.")
public class TimeSeriesValue {
+
+ @Schema(description = "The time of the value in the time series.")
+ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = GlobalDefinitions.INSTANT_JSON_PATTERN, timezone = "UTC")
private Instant time;
+
+ @Schema(description = "The value of the value in the time series.")
private Double value;
}
diff --git a/src/main/java/de/app/fivegla/integration/generic/GenericDeviceIntegrationService.java b/src/main/java/de/app/fivegla/integration/generic/GenericDeviceIntegrationService.java
index b6ee86bb..c7e4feac 100644
--- a/src/main/java/de/app/fivegla/integration/generic/GenericDeviceIntegrationService.java
+++ b/src/main/java/de/app/fivegla/integration/generic/GenericDeviceIntegrationService.java
@@ -51,6 +51,7 @@ public void persist(Manufacturer manufacturer, String id, double latitude, doubl
.build();
var device = Device.builder()
.id(FiwareDeviceId.create(manufacturerConfiguration, id))
+ .manufacturerSpecificId(id)
.deviceCategory(DeviceCategory.builder()
.value(List.of(manufacturerConfiguration.getKey()))
.build())
diff --git a/src/main/java/de/app/fivegla/integration/micasense/MicaSenseFiwareIntegrationServiceWrapper.java b/src/main/java/de/app/fivegla/integration/micasense/MicaSenseFiwareIntegrationServiceWrapper.java
index 1dc52bad..7477b1c9 100644
--- a/src/main/java/de/app/fivegla/integration/micasense/MicaSenseFiwareIntegrationServiceWrapper.java
+++ b/src/main/java/de/app/fivegla/integration/micasense/MicaSenseFiwareIntegrationServiceWrapper.java
@@ -8,10 +8,7 @@
import de.app.fivegla.fiware.DeviceIntegrationService;
import de.app.fivegla.fiware.DroneDeviceMeasurementIntegrationService;
import de.app.fivegla.fiware.api.InstantFormatter;
-import de.app.fivegla.fiware.model.Device;
-import de.app.fivegla.fiware.model.DeviceCategory;
-import de.app.fivegla.fiware.model.DeviceMeasurement;
-import de.app.fivegla.fiware.model.DroneDeviceMeasurement;
+import de.app.fivegla.fiware.model.*;
import de.app.fivegla.integration.micasense.model.MicaSenseImage;
import de.app.fivegla.monitoring.FiwareEntityMonitor;
import lombok.extern.slf4j.Slf4j;
@@ -53,12 +50,20 @@ public void createOrUpdateDevice(String droneId) {
.deviceCategory(DeviceCategory.builder()
.value(List.of(getManufacturerConfiguration().getKey()))
.build())
+ .location(fakeLocation())
+ .manufacturerSpecificId(droneId)
.id(fiwareId)
.build();
deviceIntegrationService.persist(device);
fiwareEntityMonitor.sensorsSavedOrUpdated(getManufacturerConfiguration().manufacturer());
}
+ private Location fakeLocation() {
+ return Location.builder()
+ .coordinates(List.of(0.0, 0.0))
+ .build();
+ }
+
/**
* Create a new drone device measurement in FIWARE.
*
diff --git a/src/main/java/de/app/fivegla/integration/sentek/SentekFiwareIntegrationServiceWrapper.java b/src/main/java/de/app/fivegla/integration/sentek/SentekFiwareIntegrationServiceWrapper.java
index 9a264108..51bb9a40 100644
--- a/src/main/java/de/app/fivegla/integration/sentek/SentekFiwareIntegrationServiceWrapper.java
+++ b/src/main/java/de/app/fivegla/integration/sentek/SentekFiwareIntegrationServiceWrapper.java
@@ -194,9 +194,13 @@ public void persist(Logger logger, List
+ * This variable is used to store the time at which a value was recorded in the time series.
+ */
+ @Schema(description = "The time of the value in the time series.")
+ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = GlobalDefinitions.INSTANT_JSON_PATTERN, timezone = "UTC")
+ private Instant timestamp;
+
+ /**
+ * The value of the value in the time series.
+ */
+ @Schema(description = "The value of the value in the time series.")
+ private MeasurementValues measurementValues;
}
diff --git a/src/main/java/de/app/fivegla/integration/weenat/model/MeasurementValues.java b/src/main/java/de/app/fivegla/integration/weenat/model/MeasurementValues.java
index 98d19fa9..6120e6f1 100644
--- a/src/main/java/de/app/fivegla/integration/weenat/model/MeasurementValues.java
+++ b/src/main/java/de/app/fivegla/integration/weenat/model/MeasurementValues.java
@@ -1,6 +1,7 @@
package de.app.fivegla.integration.weenat.model;
import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@@ -12,77 +13,102 @@
*/
@Getter
@Setter
+@Schema(description = "Represents a single measurement entry with various weather-related properties.")
public class MeasurementValues {
+ @Schema(description = "The temperature of the measurement.")
@JsonProperty("T")
private Double temperature;
+ @Schema(description = "The relative humidity of the measurement.")
@JsonProperty("U")
private Double relativeHumidity;
+ @Schema(description = "The cumulative rainfall of the measurement.")
@JsonProperty("RR")
private Double cumulativeRainfall;
+ @Schema(description = "The wind speed of the measurement.")
@JsonProperty("FF")
private Double windSpeed;
+ @Schema(description = "The wind gust speed of the measurement.")
@JsonProperty("FXY")
private Double windGustSpeed;
+ @Schema(description = "The soil temperature in 15 cm of the measurement.")
@JsonProperty("T_15")
private Double soilTemperature15;
+ @Schema(description = "The soil temperature in 30 cm of the measurement.")
@JsonProperty("T_30")
private Double soilTemperature30;
+ @Schema(description = "The soil temperature in 50 cm of the measurement.")
@JsonProperty("T_60")
private Double soilTemperature60;
+ @Schema(description = "The soil water potential in 15 cm of the measurement.")
@JsonProperty("WHYD_15")
private Double soilWaterPotential15;
+ @Schema(description = "The soil water potential in 30 cm of the measurement.")
@JsonProperty("WHYD_30")
private Double soilWaterPotential30;
+ @Schema(description = "The soil water potential in 60 cm of the measurement.")
@JsonProperty("WHYD_60")
private Double soilWaterPotential60;
+ @Schema(description = "The dry temperature of the measurement.")
@JsonProperty("T_DRY")
private Double dryTemperature;
+ @Schema(description = "The wet temperature of the measurement.")
@JsonProperty("T_WET")
private Double wetTemperature;
+ @Schema(description = "The leaf wetness duration of the measurement.")
@JsonProperty("LW_DRY")
private Double leafWetnessDuration;
+ @Schema(description = "The leaf wetness voltage of the measurement.")
@JsonProperty("LW_V")
private Double leafWetnessVoltage;
+ @Schema(description = "The soil temperature of the measurement.")
@JsonProperty("T_SOIL")
private Double soilTemperature;
+ @Schema(description = "The solar irradiance of the measurement.")
@JsonProperty("SSI")
- private Double solarIrridiance;
+ private Double solarIrradiance;
+ @Schema(description = "The minimum solar irradiance of the measurement.")
@JsonProperty("SSI_MIN")
- private Double minimumSolarIrridiance;
+ private Double minSolarIrradiance;
+ @Schema(description = "The maximum solar irradiance of the measurement.")
@JsonProperty("SSI_MAX")
- private Double maximumSolarIrridiance;
+ private Double maxSolarIrradiance;
+ @Schema(description = "The photosynthetically active radiation of the measurement.")
@JsonProperty("PPFD")
private Double photosyntheticallyActiveRadiation;
+ @Schema(description = "The minimum photosynthetically active radiation of the measurement.")
@JsonProperty("PPFD_MIN")
private Double minimumPhotosyntheticallyActiveRadiation;
+ @Schema(description = "The maximum photosynthetically active radiation of the measurement.")
@JsonProperty("PPFD_MAX")
private Double maximumPhotosyntheticallyActiveRadiation;
+ @Schema(description = "The dew point of the measurement.")
@JsonProperty("T_DEW")
private Double dewPoint;
+ @Schema(description = "The potential evapotranspiration of the measurement.")
@JsonProperty("ETP")
private Double potentialEvapotranspiration;
}