Record meteo module sensors in historian

This commit is contained in:
litoral05
2026-05-22 13:47:39 +01:00
parent cb63d6a237
commit db75744305
4 changed files with 60 additions and 27 deletions
@@ -2,9 +2,14 @@ package com.litoralregas.backend.acquisition.scheduler;
import com.litoralregas.backend.acquisition.polling.AcquisitionPollResult; import com.litoralregas.backend.acquisition.polling.AcquisitionPollResult;
import com.litoralregas.backend.acquisition.block.BlockPollingService; import com.litoralregas.backend.acquisition.block.BlockPollingService;
import com.litoralregas.backend.dashboard.DashboardOverviewResponse;
import com.litoralregas.backend.dashboard.DashboardOverviewService;
import com.litoralregas.backend.historian.HistorianService;
import com.litoralregas.backend.modules.meteo.MeteoModuleResponse;
import com.litoralregas.backend.modules.meteo.websocket.MeteoModuleWebSocketPublisher; import com.litoralregas.backend.modules.meteo.websocket.MeteoModuleWebSocketPublisher;
import com.litoralregas.backend.websocket.dashboard.DashboardOverviewWebSocketPublisher; import com.litoralregas.backend.websocket.dashboard.DashboardOverviewWebSocketPublisher;
import com.litoralregas.backend.websocket.telemetry.TelemetryWebSocketPublisher; import com.litoralregas.backend.websocket.telemetry.TelemetryWebSocketPublisher;
import com.litoralregas.backend.modules.meteo.MeteoModuleService;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.TaskScheduler;
@@ -23,6 +28,9 @@ public class AcquisitionSchedulerService {
private final DashboardOverviewWebSocketPublisher dashboardOverviewWebSocketPublisher; private final DashboardOverviewWebSocketPublisher dashboardOverviewWebSocketPublisher;
private final MeteoModuleWebSocketPublisher meteoModuleWebSocketPublisher; private final MeteoModuleWebSocketPublisher meteoModuleWebSocketPublisher;
private final DashboardOverviewService dashboardOverviewService;
private final MeteoModuleService meteoModuleService;
private final HistorianService historianService;
private final AcquisitionRuntimeStatus runtimeStatus = new AcquisitionRuntimeStatus(); private final AcquisitionRuntimeStatus runtimeStatus = new AcquisitionRuntimeStatus();
private final AtomicBoolean polling = new AtomicBoolean(false); private final AtomicBoolean polling = new AtomicBoolean(false);
@@ -33,7 +41,10 @@ public class AcquisitionSchedulerService {
@Qualifier("acquisitionTaskScheduler") TaskScheduler taskScheduler, @Qualifier("acquisitionTaskScheduler") TaskScheduler taskScheduler,
TelemetryWebSocketPublisher telemetryWebSocketPublisher, TelemetryWebSocketPublisher telemetryWebSocketPublisher,
DashboardOverviewWebSocketPublisher dashboardOverviewWebSocketPublisher, DashboardOverviewWebSocketPublisher dashboardOverviewWebSocketPublisher,
MeteoModuleWebSocketPublisher meteoModuleWebSocketPublisher MeteoModuleWebSocketPublisher meteoModuleWebSocketPublisher,
HistorianService historianService,
DashboardOverviewService dashboardOverviewService,
MeteoModuleService meteoModuleService
) { ) {
this.blockPollingService = blockPollingService; this.blockPollingService = blockPollingService;
this.properties = properties; this.properties = properties;
@@ -41,6 +52,9 @@ public class AcquisitionSchedulerService {
this.telemetryWebSocketPublisher = telemetryWebSocketPublisher; this.telemetryWebSocketPublisher = telemetryWebSocketPublisher;
this.dashboardOverviewWebSocketPublisher = dashboardOverviewWebSocketPublisher; this.dashboardOverviewWebSocketPublisher = dashboardOverviewWebSocketPublisher;
this.meteoModuleWebSocketPublisher = meteoModuleWebSocketPublisher; this.meteoModuleWebSocketPublisher = meteoModuleWebSocketPublisher;
this.historianService = historianService;
this.dashboardOverviewService = dashboardOverviewService;
this.meteoModuleService = meteoModuleService;
} }
@PostConstruct @PostConstruct
@@ -79,8 +93,14 @@ public class AcquisitionSchedulerService {
runtimeStatus.setLastFailedReads(result.failedReads()); runtimeStatus.setLastFailedReads(result.failedReads());
telemetryWebSocketPublisher.publishLatestTelemetry(); telemetryWebSocketPublisher.publishLatestTelemetry();
dashboardOverviewWebSocketPublisher.publishOverview();
meteoModuleWebSocketPublisher.publishLatest(); DashboardOverviewResponse overview = dashboardOverviewService.getOverview();
historianService.recordDashboardOverview(overview);
dashboardOverviewWebSocketPublisher.publishOverview(overview);
MeteoModuleResponse meteo = meteoModuleService.getLatest();
historianService.recordModuleSensors("meteo", meteo.sensors(), meteo.timestamp());
meteoModuleWebSocketPublisher.publishLatest(meteo);
} catch (Exception exception) { } catch (Exception exception) {
runtimeStatus.setLastError(exception.getMessage()); runtimeStatus.setLastError(exception.getMessage());
@@ -1,6 +1,7 @@
package com.litoralregas.backend.historian; package com.litoralregas.backend.historian;
import com.litoralregas.backend.dashboard.DashboardOverviewResponse; import com.litoralregas.backend.dashboard.DashboardOverviewResponse;
import com.litoralregas.backend.modules.shared.ModuleSensorResponse;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -150,4 +151,36 @@ public class HistorianService {
sample.getTextValue() sample.getTextValue()
); );
} }
@Transactional
public void recordModuleSensors(
String moduleName,
List<ModuleSensorResponse> sensors,
Instant sampledAt
) {
for (ModuleSensorResponse sensor : sensors) {
String keyName = moduleName + "." + sensor.key();
Object value = sensor.value();
if (value instanceof Number numberValue) {
recordNumber(
sampledAt,
keyName,
numberValue,
sensor.unit()
);
} else if (value instanceof Boolean booleanValue) {
recordBoolean(
sampledAt,
keyName,
booleanValue
);
}
}
}
} }
@@ -1,7 +1,6 @@
package com.litoralregas.backend.modules.meteo.websocket; package com.litoralregas.backend.modules.meteo.websocket;
import com.litoralregas.backend.modules.meteo.MeteoModuleResponse; import com.litoralregas.backend.modules.meteo.MeteoModuleResponse;
import com.litoralregas.backend.modules.meteo.MeteoModuleService;
import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -11,19 +10,14 @@ public class MeteoModuleWebSocketPublisher {
private static final String DESTINATION = "/topic/modules/meteo/latest"; private static final String DESTINATION = "/topic/modules/meteo/latest";
private final SimpMessagingTemplate messagingTemplate; private final SimpMessagingTemplate messagingTemplate;
private final MeteoModuleService meteoModuleService;
public MeteoModuleWebSocketPublisher( public MeteoModuleWebSocketPublisher(
SimpMessagingTemplate messagingTemplate, SimpMessagingTemplate messagingTemplate
MeteoModuleService meteoModuleService
) { ) {
this.messagingTemplate = messagingTemplate; this.messagingTemplate = messagingTemplate;
this.meteoModuleService = meteoModuleService;
} }
public void publishLatest() { public void publishLatest(MeteoModuleResponse response) {
System.out.println("Publishing meteo module websocket");
MeteoModuleResponse response = meteoModuleService.getLatest();
messagingTemplate.convertAndSend(DESTINATION, response); messagingTemplate.convertAndSend(DESTINATION, response);
} }
} }
@@ -1,8 +1,6 @@
package com.litoralregas.backend.websocket.dashboard; package com.litoralregas.backend.websocket.dashboard;
import com.litoralregas.backend.dashboard.DashboardOverviewResponse; import com.litoralregas.backend.dashboard.DashboardOverviewResponse;
import com.litoralregas.backend.dashboard.DashboardOverviewService;
import com.litoralregas.backend.historian.HistorianService;
import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -12,26 +10,14 @@ public class DashboardOverviewWebSocketPublisher {
private static final String DESTINATION = "/topic/dashboard/overview"; private static final String DESTINATION = "/topic/dashboard/overview";
private final SimpMessagingTemplate messagingTemplate; private final SimpMessagingTemplate messagingTemplate;
private final DashboardOverviewService dashboardOverviewService;
private final HistorianService historianService;
public DashboardOverviewWebSocketPublisher( public DashboardOverviewWebSocketPublisher(
SimpMessagingTemplate messagingTemplate, SimpMessagingTemplate messagingTemplate
DashboardOverviewService dashboardOverviewService,
HistorianService historianService
) { ) {
this.messagingTemplate = messagingTemplate; this.messagingTemplate = messagingTemplate;
this.dashboardOverviewService = dashboardOverviewService;
this.historianService = historianService;
} }
public void publishOverview() { public void publishOverview(DashboardOverviewResponse overview) {
DashboardOverviewResponse overview = dashboardOverviewService.getOverview();
System.out.println("Publishing dashboard overview at " + overview.timestamp());
historianService.recordDashboardOverview(overview);
messagingTemplate.convertAndSend(DESTINATION, overview); messagingTemplate.convertAndSend(DESTINATION, overview);
} }
} }