From 5cd3f1958a608fef13931a3977ba15ac15e9080d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20L=27hopital?= Date: Tue, 12 Nov 2024 16:27:50 +0100 Subject: [PATCH 1/5] Some binding enhancements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gaël L'hopital --- .../org.openhab.binding.meteofrance/README.md | 40 ++++++++++++++++++- .../handler/MeteoFranceBridgeHandler.java | 6 ++- .../internal/handler/RainForecastHandler.java | 24 +++++++---- 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/bundles/org.openhab.binding.meteofrance/README.md b/bundles/org.openhab.binding.meteofrance/README.md index 6abad3ad28933..988bed1f90a0e 100644 --- a/bundles/org.openhab.binding.meteofrance/README.md +++ b/bundles/org.openhab.binding.meteofrance/README.md @@ -41,7 +41,7 @@ The `rain-forecast` thing has this configuration parameters: |-----------|--------------------------------------------------------------| | location | Geo coordinates to be considered by the service. | -## Channels +## Channels for `vigilance` The information that are retrieved is available as these channels: @@ -78,6 +78,24 @@ The information that are retrieved is available as these channels: | 2 | Orange | Be "very vigilant" in the concerned areas | | 3 | Red | Absolute vigilance required | +## Channels for `rain-forecast` + +The information that are retrieved is available as these channels: + +| Channel ID | Item Type | Description | +|--------------|-----------|--------------------------| +| update-time | DateTime | Observation Timestamp | +| intensity | Number | Rain intensity level (*) | + +(*) Each alert level has an associated color and description: + +| Code | Description | +|------|---------------| +| 0 | Dry Weather | +| 1 | Light Rain | +| 2 | Moderate Rain | +| 3 | Heavy Rain | + ## Provided icon set This binding has its own IconProvider and makes available the following list of icons @@ -101,7 +119,10 @@ This binding has its own IconProvider and makes available the following list of meteoalert.things: ```java -Thing meteofrance:department:yvelines @ "MyCity" [department="78", refresh=12] +Bridge meteofrance:api:local "Portail Météo-France" [ apikey="ey......FIjG1MIC9lmG5t6HygPAPg=="] { + vigilance yvelines "Vigilance Météo" [ department="78" ] + rain-forecast yvelines [ location="48.764207,2.05948" ] +} ``` meteoalert.items: @@ -129,4 +150,19 @@ Image MA_icon_avalanche "Avalanche" (gMeteoAlert) {channel="meteofrance:department:yvelines:observation-time"} +Number Intensite_Pluie "Intensité Pluie" (gMeteoAlert) {channel="meteofrance:rain-forecast:yvelines:intensity" } + + ``` + +jdbc.persist: + +```java + +Items { + * : strategy = everyChange + Intensite_Pluie : strategy = forecast +} + + +``` \ No newline at end of file diff --git a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/MeteoFranceBridgeHandler.java b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/MeteoFranceBridgeHandler.java index e20abe75abd95..070997d1f551d 100644 --- a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/MeteoFranceBridgeHandler.java +++ b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/MeteoFranceBridgeHandler.java @@ -15,6 +15,7 @@ import static org.openhab.binding.meteofrance.internal.MeteoFranceBindingConstants.REQUEST_TIMEOUT_MS; import java.io.IOException; +import java.util.Locale; import java.util.Optional; import java.util.Properties; import java.util.concurrent.TimeUnit; @@ -159,10 +160,13 @@ public Optional getMeta() { } public @Nullable RainForecast getRainForecast(PointType location) { - String url = RAIN_FORECAST_BASE_URL.formatted(location.getLatitude().doubleValue(), + String url = String.format(Locale.US, RAIN_FORECAST_BASE_URL, location.getLatitude().doubleValue(), location.getLongitude().doubleValue()); try { + logger.debug("Sending rain-forecast request to: {}", url); String answer = HttpUtil.executeUrl(HttpMethod.GET, url, REQUEST_TIMEOUT_MS); + logger.debug("Received answer: {}", answer); + return deserializer.deserialize(RainForecast.class, answer); } catch (MeteoFranceException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, diff --git a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/RainForecastHandler.java b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/RainForecastHandler.java index a1e2d07ea8954..87c2a9503dd89 100644 --- a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/RainForecastHandler.java +++ b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/RainForecastHandler.java @@ -116,9 +116,9 @@ private void updateAndPublish() { location.ifPresent(loc -> { RainForecast forecast = handler.getRainForecast(loc); if (forecast != null) { + updateStatus(ThingStatus.ONLINE); setProperties(forecast.properties); updateDate(UPDATE_TIME, forecast.updateTime); - updateStatus(ThingStatus.ONLINE); } }); }, () -> logger.warn("No viable bridge")); @@ -142,19 +142,29 @@ private void setProperties(@Nullable Properties forecastProps) { private void setForecast(List forecast) { TimeSeries timeSeries = new TimeSeries(REPLACE); + ZonedDateTime now = ZonedDateTime.now(); - forecast.forEach(prevision -> { + State currentState = null; + long untilNextRun = 0; + for (Forecast prevision : forecast) { State state = prevision.rainIntensity() != RainIntensity.UNKNOWN ? new DecimalType(prevision.rainIntensity().ordinal()) : UnDefType.UNDEF; + long until = now.until(prevision.time(), ChronoUnit.SECONDS); + if (currentState == null) { + currentState = state; + untilNextRun = until; + } timeSeries.add(prevision.time().toInstant(), state); - }); + } + updateState(intensityChannelUID, currentState == null ? UnDefType.UNDEF : currentState); sendTimeSeries(intensityChannelUID, timeSeries); - Forecast current = forecast.get(0); - long until = ZonedDateTime.now().until(current.time(), ChronoUnit.SECONDS); - logger.debug("Refresh rain intensity forecast in : {}s", until); - refreshJob = Optional.of(scheduler.schedule(this::updateAndPublish, until, TimeUnit.SECONDS)); + // ensure we don't have a non positive delay + untilNextRun = Math.max(untilNextRun, 300); + + logger.debug("Refresh rain intensity forecast in: {}s", untilNextRun); + refreshJob = Optional.of(scheduler.schedule(this::updateAndPublish, untilNextRun, TimeUnit.SECONDS)); } private void updateDate(String channelId, @Nullable ZonedDateTime zonedDateTime) { From d6d1e0f8e3685587849ca86e45ec9669edf2e44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20L=27hopital?= Date: Tue, 12 Nov 2024 16:38:24 +0100 Subject: [PATCH 2/5] Correct Build errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gaël L'hopital --- bundles/org.openhab.binding.meteofrance/README.md | 2 +- .../openhab/binding/meteofrance/internal/dto/MeteoFrance.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.meteofrance/README.md b/bundles/org.openhab.binding.meteofrance/README.md index 988bed1f90a0e..6ce311048d70c 100644 --- a/bundles/org.openhab.binding.meteofrance/README.md +++ b/bundles/org.openhab.binding.meteofrance/README.md @@ -165,4 +165,4 @@ Items { } -``` \ No newline at end of file +``` diff --git a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/dto/MeteoFrance.java b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/dto/MeteoFrance.java index 12ff8839d4325..a29df45a32755 100644 --- a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/dto/MeteoFrance.java +++ b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/dto/MeteoFrance.java @@ -55,8 +55,8 @@ public record Product(// Periods periods) { // périodes concernées par la Vigilance public Optional getBlocItem(Domain searched) { - return textBlocItems != null ? textBlocItems.stream().filter(ti -> ti.validFor(searched)).findFirst() - : Optional.empty(); + List local = textBlocItems; + return local != null ? local.stream().filter(ti -> ti.validFor(searched)).findFirst() : Optional.empty(); } public Optional getPeriod(Term term) { From 83732cd0b80ea2240798906eac1d792ba045f0d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20L=27hopital?= Date: Tue, 12 Nov 2024 17:31:13 +0100 Subject: [PATCH 3/5] Correct README.MD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gaël L'hopital --- bundles/org.openhab.binding.meteofrance/README.md | 2 +- .../internal/db/DepartmentDbService.java | 14 +++++++------- .../internal/handler/RainForecastHandler.java | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bundles/org.openhab.binding.meteofrance/README.md b/bundles/org.openhab.binding.meteofrance/README.md index 6ce311048d70c..cb30a1eeef644 100644 --- a/bundles/org.openhab.binding.meteofrance/README.md +++ b/bundles/org.openhab.binding.meteofrance/README.md @@ -87,7 +87,7 @@ The information that are retrieved is available as these channels: | update-time | DateTime | Observation Timestamp | | intensity | Number | Rain intensity level (*) | -(*) Each alert level has an associated color and description: +(*) Rain intensity values and associated descriptions: | Code | Description | |------|---------------| diff --git a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/db/DepartmentDbService.java b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/db/DepartmentDbService.java index 62aee3170aad9..ff797e40d1780 100644 --- a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/db/DepartmentDbService.java +++ b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/db/DepartmentDbService.java @@ -22,7 +22,6 @@ import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.library.types.PointType; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -49,6 +48,11 @@ public class DepartmentDbService { public record Department(String id, String name, double northestLat, double southestLat, double eastestLon, double westestLon) { + + boolean contains(double latitude, double longitude) { + return northestLat >= latitude && southestLat <= latitude && // + westestLon <= longitude && eastestLon >= longitude; + } } @Activate @@ -58,7 +62,7 @@ public DepartmentDbService() { Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) { Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); departments.addAll(Arrays.asList(gson.fromJson(reader, Department[].class))); - logger.debug("Successfully loaded {} departments", departments.size()); + logger.debug("Successfully loaded {} French departments", departments.size()); } catch (IOException | JsonSyntaxException | JsonIOException e) { logger.warn("Unable to load departments list: {}", e.getMessage()); } @@ -67,11 +71,7 @@ public DepartmentDbService() { public List getBounding(PointType location) { double latitude = location.getLatitude().doubleValue(); double longitude = location.getLongitude().doubleValue(); - return departments.stream().filter(dep -> dep.northestLat >= latitude && dep.southestLat <= latitude - && dep.westestLon <= longitude && dep.eastestLon >= longitude).toList(); + return departments.stream().filter(dep -> dep.contains(latitude, longitude)).toList(); } - public @Nullable Department getDept(String deptId) { - return departments.stream().filter(dep -> dep.id.equalsIgnoreCase(deptId)).findFirst().orElse(null); - } } diff --git a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/RainForecastHandler.java b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/RainForecastHandler.java index 87c2a9503dd89..c802c8dcd2f23 100644 --- a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/RainForecastHandler.java +++ b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/handler/RainForecastHandler.java @@ -150,18 +150,18 @@ private void setForecast(List forecast) { State state = prevision.rainIntensity() != RainIntensity.UNKNOWN ? new DecimalType(prevision.rainIntensity().ordinal()) : UnDefType.UNDEF; - long until = now.until(prevision.time(), ChronoUnit.SECONDS); if (currentState == null) { currentState = state; - untilNextRun = until; + if (prevision.time().isAfter(now)) { + untilNextRun = now.until(prevision.time(), ChronoUnit.SECONDS); + } } timeSeries.add(prevision.time().toInstant(), state); } updateState(intensityChannelUID, currentState == null ? UnDefType.UNDEF : currentState); sendTimeSeries(intensityChannelUID, timeSeries); - // ensure we don't have a non positive delay - untilNextRun = Math.max(untilNextRun, 300); + untilNextRun = untilNextRun != 0 ? untilNextRun : 300; logger.debug("Refresh rain intensity forecast in: {}s", untilNextRun); refreshJob = Optional.of(scheduler.schedule(this::updateAndPublish, untilNextRun, TimeUnit.SECONDS)); From 29c457969cd34f889419cb3572904af4c1e15858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20L=27hopital?= Date: Tue, 12 Nov 2024 17:36:04 +0100 Subject: [PATCH 4/5] Apply spotless MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gaël L'hopital --- .../binding/meteofrance/internal/db/DepartmentDbService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/db/DepartmentDbService.java b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/db/DepartmentDbService.java index ff797e40d1780..a818c73d96086 100644 --- a/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/db/DepartmentDbService.java +++ b/bundles/org.openhab.binding.meteofrance/src/main/java/org/openhab/binding/meteofrance/internal/db/DepartmentDbService.java @@ -73,5 +73,4 @@ public List getBounding(PointType location) { double longitude = location.getLongitude().doubleValue(); return departments.stream().filter(dep -> dep.contains(latitude, longitude)).toList(); } - } From e2de98832fa0006372fde826c26d1d339f711511 Mon Sep 17 00:00:00 2001 From: lsiepel Date: Wed, 20 Nov 2024 23:31:58 +0100 Subject: [PATCH 5/5] Update bundles/org.openhab.binding.meteofrance/README.md Signed-off-by: lsiepel --- bundles/org.openhab.binding.meteofrance/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/bundles/org.openhab.binding.meteofrance/README.md b/bundles/org.openhab.binding.meteofrance/README.md index cb30a1eeef644..993db9bfc7ed8 100644 --- a/bundles/org.openhab.binding.meteofrance/README.md +++ b/bundles/org.openhab.binding.meteofrance/README.md @@ -151,8 +151,6 @@ Image MA_icon_avalanche "Avalanche" (gMeteoAlert) {channel="meteofrance:department:yvelines:observation-time"} Number Intensite_Pluie "Intensité Pluie" (gMeteoAlert) {channel="meteofrance:rain-forecast:yvelines:intensity" } - - ``` jdbc.persist: