Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] main from openhab:main #78

Merged
merged 1 commit into from
Nov 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions bundles/org.openhab.binding.meteoalerte/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down Expand Up @@ -72,14 +72,14 @@ meteoalert.items:
```
Group gMeteoAlert "Alertes Météo" <weather>
String MA_Dept78 "Département 78 [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:comment"}
String MA_etat_canicule "Canicule [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:canicule"}
String MA_etat_grand_froid "Grand Froid [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:grand-froid"}
String MA_etat_pluie_inondation "Pluie-Inondation [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:pluie-inondation"}
String MA_etat_neige "Neige [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:neige"}
String MA_etat_vent "Vent [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:vent"}
String MA_etat_inondation "Inondation [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:inondation"}
String MA_etat_orage "Orage [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:orage"}
String MA_etat_avalanche "Avalanches [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:avalanches"}
Number MA_etat_canicule "Canicule [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:canicule"}
Number MA_etat_grand_froid "Grand Froid [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:grand-froid"}
Number MA_etat_pluie_inondation "Pluie-Inondation [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:pluie-inondation"}
Number MA_etat_neige "Neige [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:neige"}
Number MA_etat_vent "Vent [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:vent"}
Number MA_etat_inondation "Inondation [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:inondation"}
Number MA_etat_orage "Orage [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:orage"}
Number MA_etat_avalanche "Avalanches [%s]" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:avalanches"}

Image MA_icon_canicule "Canicule" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:canicule-icon"}
Image MA_icon_grand_froid "Grand Froid" <aqi> (gMeteoAlert) {channel="meteoalerte:department:yvelines:grand-froid-icon"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,15 @@

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;
Expand All @@ -34,6 +31,7 @@
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;
Expand All @@ -43,9 +41,8 @@
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;

Expand All @@ -61,7 +58,7 @@
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<AlertLevel, String> ALERT_COLORS = Map.ofEntries(
Expand Down Expand Up @@ -91,7 +88,7 @@ public void initialize() {
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);
}

Expand Down Expand Up @@ -135,45 +132,48 @@ private void updateAndPublish() {
* @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;
}

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);
}
}

Expand All @@ -182,4 +182,19 @@ public void updateDate(String channelId, ZonedDateTime zonedDateTime) {
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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,7 +33,7 @@ public class ApiResponse {
@SerializedName("nhits")
private int nHits;
private @Nullable Parameters parameters;
private Record[] records = {};
private List<Record> records = new ArrayList<>();

public int getNHits() {
return nHits;
Expand All @@ -44,7 +47,7 @@ public Optional<Parameters> getParameters() {
return Optional.empty();
}

public Record[] getRecords() {
return records;
public Stream<Record> getRecords() {
return records.stream();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,14 @@
</thing-type>

<channel-type id="alert-level">
<item-type>String</item-type>
<item-type>Number</item-type>
<label>Alerte</label>
<state readOnly="true">
<options>
<option value="GREEN">Vert</option>
<option value="YELLOW">Jaune</option>
<option value="ORANGE">Orange</option>
<option value="RED">Rouge</option>
<option value="0">Vert</option>
<option value="1">Jaune</option>
<option value="2">Orange</option>
<option value="3">Rouge</option>
</options>
</state>
</channel-type>
Expand Down