From afe711994a4e5c26309a2e99c5c1f338cc3d0b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20L=27hopital?= Date: Mon, 9 Nov 2020 21:51:39 +0100 Subject: [PATCH] [meteoalerte] Addressing Issue #8543 (#8961) * [meteoalerte] Addressing Issue #8543 * Small change * Adding charset to byte conversion Signed-off-by: clinique --- .../org.openhab.binding.meteoalerte/README.md | 34 ++++---- .../internal/handler/MeteoAlerteHandler.java | 83 +++++++++++-------- .../internal/json/ApiResponse.java | 9 +- .../resources/OH-INF/thing/thing-types.xml | 10 +-- 4 files changed, 77 insertions(+), 59 deletions(-) diff --git a/bundles/org.openhab.binding.meteoalerte/README.md b/bundles/org.openhab.binding.meteoalerte/README.md index 29bccfe74..6be47e993 100644 --- a/bundles/org.openhab.binding.meteoalerte/README.md +++ b/bundles/org.openhab.binding.meteoalerte/README.md @@ -30,15 +30,15 @@ The Météo Alerte information that are retrieved is available as these channels | observation-time | DateTime | Date and time of report validity start | | end-time | DateTime | Date and time of report validity end | | comment | String | General comments on alerts for the department | -| vent | String | Wind alert level (*) | -| pluie-inondation | String | Rain alert level (*) | -| orage | String | Storm alert level (*) | -| inondation | String | Flood alert level (*) | -| neige | String | Snow alert level (*) | -| canicule | String | Heat alert level (*) | -| grand-froid | String | Cold alert level (*) | -| avalanches | String | Avalanche alert level (*) | -| vague-submersion | String | Wave submersion alert level (*) | +| vent | Number | Wind alert level (*) | +| pluie-inondation | Number | Rain alert level (*) | +| orage | Number | Storm alert level (*) | +| inondation | Number | Flood alert level (*) | +| neige | Number | Snow alert level (*) | +| canicule | Number | Heat alert level (*) | +| grand-froid | Number | Cold alert level (*) | +| avalanches | Number | Avalanche alert level (*) | +| vague-submersion | Number | Wave submersion alert level (*) | | pluie-inondation-icon | Image | Pictogram of the Rain alert level | | vent-icon | Image | Pictogram of the Wind alert level | | orage-icon | Image | Pictogram of Storm alert level | @@ -72,14 +72,14 @@ meteoalert.items: ``` Group gMeteoAlert "Alertes Météo" String MA_Dept78 "Département 78 [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:comment"} - String MA_etat_canicule "Canicule [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:canicule"} - String MA_etat_grand_froid "Grand Froid [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:grand-froid"} - String MA_etat_pluie_inondation "Pluie-Inondation [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:pluie-inondation"} - String MA_etat_neige "Neige [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:neige"} - String MA_etat_vent "Vent [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:vent"} - String MA_etat_inondation "Inondation [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:inondation"} - String MA_etat_orage "Orage [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:orage"} - String MA_etat_avalanche "Avalanches [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:avalanches"} + Number MA_etat_canicule "Canicule [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:canicule"} + Number MA_etat_grand_froid "Grand Froid [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:grand-froid"} + Number MA_etat_pluie_inondation "Pluie-Inondation [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:pluie-inondation"} + Number MA_etat_neige "Neige [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:neige"} + Number MA_etat_vent "Vent [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:vent"} + Number MA_etat_inondation "Inondation [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:inondation"} + Number MA_etat_orage "Orage [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:orage"} + Number MA_etat_avalanche "Avalanches [%s]" (gMeteoAlert) {channel="meteoalerte:department:yvelines:avalanches"} Image MA_icon_canicule "Canicule" (gMeteoAlert) {channel="meteoalerte:department:yvelines:canicule-icon"} Image MA_icon_grand_froid "Grand Froid" (gMeteoAlert) {channel="meteoalerte:department:yvelines:grand-froid-icon"} diff --git a/bundles/org.openhab.binding.meteoalerte/src/main/java/org/openhab/binding/meteoalerte/internal/handler/MeteoAlerteHandler.java b/bundles/org.openhab.binding.meteoalerte/src/main/java/org/openhab/binding/meteoalerte/internal/handler/MeteoAlerteHandler.java index e29a41fb5..7dfcc2995 100644 --- a/bundles/org.openhab.binding.meteoalerte/src/main/java/org/openhab/binding/meteoalerte/internal/handler/MeteoAlerteHandler.java +++ b/bundles/org.openhab.binding.meteoalerte/src/main/java/org/openhab/binding/meteoalerte/internal/handler/MeteoAlerteHandler.java @@ -14,18 +14,15 @@ package org.openhab.binding.meteoalerte.internal.handler; import static org.openhab.binding.meteoalerte.internal.MeteoAlerteBindingConstants.*; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.net.MalformedURLException; +import java.nio.charset.StandardCharsets; import java.time.ZonedDateTime; import java.util.AbstractMap; -import java.util.Arrays; import java.util.Map; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -34,6 +31,7 @@ import org.openhab.binding.meteoalerte.internal.json.ApiResponse; import org.openhab.binding.meteoalerte.internal.json.ResponseFieldDTO.AlertLevel; import org.openhab.core.io.net.http.HttpUtil; import org.openhab.core.library.types.DateTimeType; +import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.RawType; import org.openhab.core.library.types.StringType; import org.openhab.core.thing.ChannelUID; @@ -43,9 +41,8 @@ import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; +import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; -import org.osgi.framework.Bundle; -import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,7 +58,7 @@ import com.google.gson.Gson; public class MeteoAlerteHandler extends BaseThingHandler { private static final String URL = "https://public.opendatasoft.com/api/records/1.0/search/?dataset=risques-meteorologiques-copy&" + "facet=etat_vent&facet=etat_pluie_inondation&facet=etat_orage&facet=etat_inondation&facet=etat_neige&facet=etat_canicule&" - + "facet=etat_grand_froid&facet=etat_avalanches&refine.nom_dept="; + + "facet=etat_grand_froid&facet=etat_avalanches&refine.nom_dept=%s"; private static final int TIMEOUT_MS = 30000; private static final String UNKNOWN_COLOR = "b3b3b3"; private static final Map ALERT_COLORS = Map.ofEntries( @@ -91,7 +88,7 @@ public class MeteoAlerteHandler extends BaseThingHandler { logger.debug("config refresh = {}", config.refresh); updateStatus(ThingStatus.UNKNOWN); - queryUrl = URL + config.department; + queryUrl = String.format(URL, config.department); refreshJob = scheduler.scheduleWithFixedDelay(this::updateAndPublish, 0, config.refresh, TimeUnit.MINUTES); } @@ -135,29 +132,30 @@ public class MeteoAlerteHandler extends BaseThingHandler { * @param channelId the id identifying the channel to be updated */ private void updateChannels(ApiResponse apiResponse) { - Arrays.stream(apiResponse.getRecords()).findFirst() - .ifPresent((record) -> record.getResponseFieldDTO().ifPresent(fields -> { - updateAlert(WIND, fields.getVent()); - updateAlert(RAIN, fields.getPluieInondation()); - updateAlert(STORM, fields.getOrage()); - updateAlert(FLOOD, fields.getInondation()); - updateAlert(SNOW, fields.getNeige()); - updateAlert(HEAT, fields.getCanicule()); - updateAlert(FREEZE, fields.getGrandFroid()); - updateAlert(AVALANCHE, fields.getAvalanches()); - updateAlert(WAVE, fields.getVagueSubmersion()); - updateState(COMMENT, new StringType(fields.getVigilanceComment())); - fields.getDateInsert().ifPresent(date -> updateDate(OBSERVATION_TIME, date)); - fields.getDatePrevue().ifPresent(date -> updateDate(END_TIME, date)); - })); + apiResponse.getRecords().findFirst().ifPresent((record) -> record.getResponseFieldDTO().ifPresent(fields -> { + updateAlert(WIND, fields.getVent()); + updateAlert(RAIN, fields.getPluieInondation()); + updateAlert(STORM, fields.getOrage()); + updateAlert(FLOOD, fields.getInondation()); + updateAlert(SNOW, fields.getNeige()); + updateAlert(HEAT, fields.getCanicule()); + updateAlert(FREEZE, fields.getGrandFroid()); + updateAlert(AVALANCHE, fields.getAvalanches()); + updateAlert(WAVE, fields.getVagueSubmersion()); + updateState(COMMENT, new StringType(fields.getVigilanceComment())); + fields.getDateInsert().ifPresent(date -> updateDate(OBSERVATION_TIME, date)); + fields.getDatePrevue().ifPresent(date -> updateDate(END_TIME, date)); + })); } - public @Nullable String getResource(String iconPath) { - Bundle bundle = FrameworkUtil.getBundle(getClass()); - try (InputStream stream = bundle.getResource(iconPath).openStream()) { - return new BufferedReader(new InputStreamReader(stream)).lines().collect(Collectors.joining("\n")); - } catch (IOException e) { - logger.warn("Unable to load ressource '{}' : {}", iconPath, e.getMessage()); + public byte @Nullable [] getResource(String iconPath) { + ClassLoader classLoader = MeteoAlerteHandler.class.getClassLoader(); + if (classLoader != null) { + try (InputStream stream = classLoader.getResourceAsStream(iconPath)) { + return stream != null ? stream.readAllBytes() : null; + } catch (IOException e) { + logger.warn("Unable to load ressource '{}' : {}", iconPath, e.getMessage()); + } } return null; } @@ -165,15 +163,17 @@ public class MeteoAlerteHandler extends BaseThingHandler { public void updateAlert(String channelId, AlertLevel value) { String channelIcon = channelId + "-icon"; if (isLinked(channelId)) { - updateState(channelId, value != AlertLevel.UNKNOWN ? new StringType(value.name()) : UnDefType.UNDEF); + updateState(channelId, getAlertLevel(value)); } if (isLinked(channelIcon)) { - String resource = getResource(String.format("picto/%s.svg", channelId)); - if (resource != null) { + State result = UnDefType.UNDEF; + byte[] bytes = getResource(String.format("picto/%s.svg", channelId)); + if (bytes != null) { + String resource = new String(bytes, StandardCharsets.UTF_8); resource = resource.replaceAll(UNKNOWN_COLOR, ALERT_COLORS.getOrDefault(value, UNKNOWN_COLOR)); + result = new RawType(resource.getBytes(StandardCharsets.UTF_8), "image/svg+xml"); } - updateState(channelIcon, - resource != null ? new RawType(resource.getBytes(), "image/svg+xml") : UnDefType.UNDEF); + updateState(channelIcon, result); } } @@ -182,4 +182,19 @@ public class MeteoAlerteHandler extends BaseThingHandler { updateState(channelId, new DateTimeType(zonedDateTime)); } } + + public State getAlertLevel(AlertLevel alert) { + switch (alert) { + case GREEN: + return DecimalType.ZERO; + case YELLOW: + return new DecimalType(1); + case ORANGE: + return new DecimalType(2); + case RED: + return new DecimalType(3); + default: + return UnDefType.UNDEF; + } + } } diff --git a/bundles/org.openhab.binding.meteoalerte/src/main/java/org/openhab/binding/meteoalerte/internal/json/ApiResponse.java b/bundles/org.openhab.binding.meteoalerte/src/main/java/org/openhab/binding/meteoalerte/internal/json/ApiResponse.java index 54119fcba..499efe01f 100644 --- a/bundles/org.openhab.binding.meteoalerte/src/main/java/org/openhab/binding/meteoalerte/internal/json/ApiResponse.java +++ b/bundles/org.openhab.binding.meteoalerte/src/main/java/org/openhab/binding/meteoalerte/internal/json/ApiResponse.java @@ -12,7 +12,10 @@ */ package org.openhab.binding.meteoalerte.internal.json; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -30,7 +33,7 @@ public class ApiResponse { @SerializedName("nhits") private int nHits; private @Nullable Parameters parameters; - private Record[] records = {}; + private List records = new ArrayList<>(); public int getNHits() { return nHits; @@ -44,7 +47,7 @@ public class ApiResponse { return Optional.empty(); } - public Record[] getRecords() { - return records; + public Stream getRecords() { + return records.stream(); } } diff --git a/bundles/org.openhab.binding.meteoalerte/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.meteoalerte/src/main/resources/OH-INF/thing/thing-types.xml index b83f35eeb..fafa8336c 100644 --- a/bundles/org.openhab.binding.meteoalerte/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.meteoalerte/src/main/resources/OH-INF/thing/thing-types.xml @@ -185,14 +185,14 @@ - String + Number - - - - + + + +