- MOCK_MODE=true bypasses API call with hardcoded critical readings - Aeration recommendation via Co2Level thresholds (resolveLevel / isAlertable) - Webhook URL now defaults to configured Teams channel
This commit is contained in:
@@ -27,7 +27,8 @@ public class NotificationProperties {
|
||||
private String apiUrl = "http://localhost:8080";
|
||||
private long pollIntervalMs = 60_000;
|
||||
private Thresholds thresholds = new Thresholds();
|
||||
private String alertFromLevel = "poor";
|
||||
private String alertFromLevel = "poor";
|
||||
private boolean mockMode = false;
|
||||
|
||||
public String getApiUrl() { return apiUrl; }
|
||||
public void setApiUrl(String apiUrl) { this.apiUrl = apiUrl; }
|
||||
@@ -40,6 +41,9 @@ public class NotificationProperties {
|
||||
|
||||
public String getAlertFromLevel() { return alertFromLevel; }
|
||||
public void setAlertFromLevel(String alertFromLevel) { this.alertFromLevel = alertFromLevel; }
|
||||
|
||||
public boolean isMockMode() { return mockMode; }
|
||||
public void setMockMode(boolean mockMode) { this.mockMode = mockMode; }
|
||||
}
|
||||
|
||||
public static class Thresholds {
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@@ -17,9 +18,15 @@ public class AirQualityScheduler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AirQualityScheduler.class);
|
||||
|
||||
private final AirQualityService airQualityService;
|
||||
private final TeamsNotificationService teamsService;
|
||||
private final NotificationProperties props;
|
||||
private static final List<SensorReading> MOCK_READINGS = List.of(
|
||||
new SensorReading("A1", "Salle A1", 2150, 23.5, 55, "closed", Instant.now()),
|
||||
new SensorReading("A2", "Salle A2", 1520, 22.0, 48, "open", Instant.now()),
|
||||
new SensorReading("B1", "Salle B1", 780, 21.0, 42, "closed", Instant.now())
|
||||
);
|
||||
|
||||
private final AirQualityService airQualityService;
|
||||
private final TeamsNotificationService teamsService;
|
||||
private final NotificationProperties props;
|
||||
|
||||
public AirQualityScheduler(AirQualityService airQualityService,
|
||||
TeamsNotificationService teamsService,
|
||||
@@ -29,20 +36,16 @@ public class AirQualityScheduler {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls air quality data at the configured interval and sends a Teams alert
|
||||
* for each room whose CO₂ level reaches or exceeds the configured threshold.
|
||||
*
|
||||
* The interval is read from the environment variable POLL_INTERVAL_MS
|
||||
* (default: 60 000 ms). Spring's @Scheduled only supports fixed values at
|
||||
* compile-time, so we use fixedDelayString with a SpEL expression instead.
|
||||
*/
|
||||
@Scheduled(fixedDelayString = "${notification.air-quality.poll-interval-ms:60000}",
|
||||
initialDelayString = "5000")
|
||||
@Scheduled(fixedDelayString = "${notification.air-quality.poll-interval-ms:60000}",
|
||||
initialDelayString = "5000")
|
||||
public void checkAirQuality() {
|
||||
log.debug("Polling air quality data…");
|
||||
boolean mockMode = props.getAirQuality().isMockMode();
|
||||
log.debug("Polling air quality data… (mock={})", mockMode);
|
||||
|
||||
List<SensorReading> readings = mockMode
|
||||
? MOCK_READINGS
|
||||
: airQualityService.fetchLatestReadings();
|
||||
|
||||
List<SensorReading> readings = airQualityService.fetchLatestReadings();
|
||||
if (readings.isEmpty()) {
|
||||
log.warn("No readings returned — skipping this cycle");
|
||||
return;
|
||||
|
||||
@@ -4,7 +4,7 @@ spring:
|
||||
|
||||
notification:
|
||||
teams:
|
||||
webhook-url: ${TEAMS_WEBHOOK_URL:}
|
||||
webhook-url: ${TEAMS_WEBHOOK_URL:https://defaulta372f724c0b24ea0abfb0eb8c6f84e.40.environment.api.powerplatform.com:443/powerautomate/automations/direct/workflows/e661f41b50314eeebaccc123a0fcc129/triggers/manual/paths/invoke?api-version=1&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=0L78wU0kY2jjnXUwehf6lkDnA61vQOD4SuTHcRsdOX8}
|
||||
air-quality:
|
||||
api-url: ${AIR_QUALITY_API_URL:http://localhost:8080}
|
||||
poll-interval-ms: ${POLL_INTERVAL_MS:60000}
|
||||
@@ -15,3 +15,5 @@ notification:
|
||||
critical: 2000
|
||||
# Minimum level that triggers a notification (excellent / good / moderate / poor / critical)
|
||||
alert-from-level: poor
|
||||
# Set to true to skip the API call and use hardcoded mock readings (for local testing)
|
||||
mock-mode: ${MOCK_MODE:false}
|
||||
|
||||
Reference in New Issue
Block a user