[VigiCrues] Adding localization and a bit of code cleansing. (#10992)

* Adding localization and a bit of code cleansing.

Signed-off-by: clinique <gael@lhopital.org>

* Review corrections

Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
Gaël L'hopital 2021-07-17 22:37:41 +02:00 committed by GitHub
parent f8157549ef
commit 71638cead2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 142 additions and 85 deletions

View File

@ -12,7 +12,6 @@
*/
package org.openhab.binding.vigicrues.internal;
import java.util.Collections;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
@ -27,10 +26,8 @@ import org.openhab.core.thing.ThingTypeUID;
@NonNullByDefault
public class VigiCruesBindingConstants {
public static final String BINDING_ID = "vigicrues";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_STATION = new ThingTypeUID(BINDING_ID, "station");
// List of Thing Type UIDs
public static final ThingTypeUID THING_TYPE_STATION = new ThingTypeUID("vigicrues", "station");
// List of all Channel id's
public static final String OBSERVATION_TIME = "observation-time";
@ -50,5 +47,5 @@ public class VigiCruesBindingConstants {
public static final String LOCATION = "Location";
public static final String FLOOD = "Crue";
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_STATION);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_STATION);
}

View File

@ -16,6 +16,8 @@ import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.Locale;
import javax.ws.rs.HttpMethod;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.vigicrues.internal.dto.hubeau.HubEauResponse;
import org.openhab.binding.vigicrues.internal.dto.opendatasoft.OpenDatasoftResponse;
@ -45,7 +47,9 @@ import com.google.gson.JsonSyntaxException;
@Component(service = ApiHandler.class)
@NonNullByDefault
public class ApiHandler {
private static final String HUBEAU_URL = "https://hubeau.eaufrance.fr/api/v1/hydrometrie/referentiel/stations?format=json&size=2000";
private static final int TIMEOUT_MS = 30000;
private final Gson gson;
@Activate
@ -58,13 +62,10 @@ public class ApiHandler {
}
private <T> T execute(String url, Class<T> responseType) throws VigiCruesException {
String jsonResponse = "";
try {
jsonResponse = HttpUtil.executeUrl("GET", url, TIMEOUT_MS);
String jsonResponse = HttpUtil.executeUrl(HttpMethod.GET, url, TIMEOUT_MS);
return gson.fromJson(jsonResponse, responseType);
} catch (IOException e) {
throw new VigiCruesException(e);
} catch (JsonSyntaxException e) {
} catch (IOException | JsonSyntaxException e) {
throw new VigiCruesException(e);
}
}
@ -95,16 +96,13 @@ public class ApiHandler {
}
public HubEauResponse discoverStations(PointType location, int range) throws VigiCruesException {
final String BASE_URL = "https://hubeau.eaufrance.fr/api/v1/hydrometrie/referentiel/stations?format=json&size=2000";
return execute(
BASE_URL + String.format(Locale.US, "&latitude=%.2f&longitude=%.2f&distance=%d",
String.format(Locale.US, "%s&latitude=%.2f&longitude=%.2f&distance=%d", HUBEAU_URL,
location.getLatitude().floatValue(), location.getLongitude().floatValue(), range),
HubEauResponse.class);
}
public HubEauResponse discoverStations(String stationId) throws VigiCruesException {
final String BASE_URL = "https://hubeau.eaufrance.fr/api/v1/hydrometrie/referentiel/stations?format=json&size=2000";
return execute(BASE_URL + String.format("&code_station=%s", stationId), HubEauResponse.class);
return execute(String.format("%s&code_station=%s", HUBEAU_URL, stationId), HubEauResponse.class);
}
}

View File

@ -27,10 +27,6 @@ public class VigiCruesException extends Exception {
super(null, e);
}
public VigiCruesException(String msg, Throwable cause) {
super(msg, cause);
}
public VigiCruesException(String msg) {
super(msg, null);
}

View File

@ -29,32 +29,20 @@ import com.google.gson.annotations.SerializedName;
@NonNullByDefault
public class VigiCruesFields {
@SerializedName("debit")
private @Nullable Double flow;
private double flow = -1;
@SerializedName("hauteur")
private @Nullable Double height;
private double height = -1;
private @Nullable ZonedDateTime timestamp;
public Optional<ZonedDateTime> getTimestamp() {
ZonedDateTime timestamp = this.timestamp;
if (timestamp != null) {
return Optional.of(timestamp);
}
return Optional.empty();
return Optional.ofNullable(timestamp);
}
public Optional<Double> getFlow() {
Double flow = this.flow;
if (flow != null) {
return Optional.of(flow);
}
return Optional.empty();
public double getFlow() {
return flow;
}
public Optional<Double> getHeight() {
Double height = this.height;
if (height != null) {
return Optional.of(height);
}
return Optional.empty();
public double getHeight() {
return height;
}
}

View File

@ -12,13 +12,13 @@
*/
package org.openhab.binding.vigicrues.internal.dto.vigicrues;
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.*;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants;
import com.google.gson.annotations.SerializedName;
/**
@ -36,21 +36,20 @@ public class CdStationHydro {
public class CruesHistorique {
@SerializedName("LbUsuel")
public String name;
private String name;
@SerializedName("ValHauteur")
public double height;
private double height;
@SerializedName("ValDebit")
public double flow;
private double flow;
public Map<String, String> getDescription() {
Map<String, String> result = new HashMap<>();
if (height != 0) {
result.put(String.format("%s %s (%s)", VigiCruesBindingConstants.FLOOD,
VigiCruesBindingConstants.HEIGHT, name), String.format(Locale.US, "%.2f m", height));
result.put(String.format("%s %s (%s)", FLOOD, HEIGHT, name),
String.format(Locale.US, "%.2f m", height));
}
if (flow != 0) {
result.put(String.format("%s %s (%s)", VigiCruesBindingConstants.FLOOD, VigiCruesBindingConstants.FLOW,
name), String.format(Locale.US, "%.2f m³/s", flow));
result.put(String.format("%s %s (%s)", FLOOD, FLOW, name), String.format(Locale.US, "%.2f m³/s", flow));
}
return result;
}

View File

@ -162,21 +162,21 @@ public class VigiCruesHandler extends BaseThingHandler {
}
} catch (VigiCruesException e) {
logger.info("Historical flooding data are not available {} : {}", config.id, e.getMessage());
channels.removeIf(channel -> (channel.getUID().getId().contains(RELATIVE_PREFIX)));
channels.removeIf(channel -> channel.getUID().getId().contains(RELATIVE_PREFIX));
}
if (!properties.containsKey(TRONCON)) {
channels.removeIf(channel -> (channel.getUID().getId().contains(ALERT)));
channels.removeIf(channel -> (channel.getUID().getId().contains(COMMENT)));
channels.removeIf(channel -> channel.getUID().getId().contains(ALERT));
channels.removeIf(channel -> channel.getUID().getId().contains(COMMENT));
}
try {
OpenDatasoftResponse measures = apiHandler.getMeasures(config.id);
measures.getFirstRecord().ifPresent(field -> {
if (field.getHeight().isEmpty()) {
if (field.getHeight() == -1) {
channels.removeIf(channel -> (channel.getUID().getId().contains(HEIGHT)));
}
if (field.getFlow().isEmpty()) {
if (field.getFlow() == -1) {
channels.removeIf(channel -> (channel.getUID().getId().contains(FLOW)));
}
});
@ -194,11 +194,11 @@ public class VigiCruesHandler extends BaseThingHandler {
public void dispose() {
logger.debug("Disposing the VigiCrues handler.");
ScheduledFuture<?> refreshJob = this.refreshJob;
if (refreshJob != null) {
refreshJob.cancel(true);
ScheduledFuture<?> localJob = refreshJob;
if (localJob != null) {
localJob.cancel(true);
}
this.refreshJob = null;
refreshJob = null;
}
@Override
@ -213,17 +213,21 @@ public class VigiCruesHandler extends BaseThingHandler {
try {
OpenDatasoftResponse measures = apiHandler.getMeasures(config.id);
measures.getFirstRecord().ifPresent(field -> {
field.getHeight().ifPresent(height -> {
double height = field.getHeight();
if (height != -1) {
updateQuantity(HEIGHT, height, SIUnits.METRE);
updateRelativeMeasure(RELATIVE_HEIGHT, referenceHeights, height);
});
field.getFlow().ifPresent(flow -> {
}
double flow = field.getFlow();
if (flow != -1) {
updateQuantity(FLOW, flow, Units.CUBICMETRE_PER_SECOND);
updateRelativeMeasure(RELATIVE_FLOW, referenceFlows, flow);
});
}
field.getTimestamp().ifPresent(date -> updateDate(OBSERVATION_TIME, date));
});
String currentPortion = this.portion;
String currentPortion = portion;
if (currentPortion != null) {
InfoVigiCru status = apiHandler.getTronconStatus(currentPortion);
updateAlert(ALERT, status.vicInfoVigiCru.vicNivInfoVigiCru - 1);
@ -255,13 +259,13 @@ public class VigiCruesHandler extends BaseThingHandler {
}
}
public void updateDate(String channelId, ZonedDateTime zonedDateTime) {
private void updateDate(String channelId, ZonedDateTime zonedDateTime) {
if (isLinked(channelId)) {
updateState(channelId, new DateTimeType(zonedDateTime));
}
}
public void updateAlert(String channelId, int value) {
private void updateAlert(String channelId, int value) {
String channelIcon = channelId + "-icon";
if (isLinked(channelId)) {
updateState(channelId, new DecimalType(value));
@ -272,11 +276,14 @@ public class VigiCruesHandler extends BaseThingHandler {
}
}
public byte @Nullable [] getResource(String iconPath) {
try (InputStream stream = VigiCruesHandler.class.getClassLoader().getResourceAsStream(iconPath)) {
return stream.readAllBytes();
} catch (IOException e) {
logger.warn("Unable to load ressource '{}' : {}", iconPath, e.getMessage());
private byte @Nullable [] getResource(String iconPath) {
ClassLoader classLoader = VigiCruesHandler.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;
}

View File

@ -4,6 +4,6 @@
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>VigiCrues Binding</name>
<description>Retrieves VigiCrues levels in France</description>
<description>Retrieves rivers levels and alerts in France</description>
</binding:binding>

View File

@ -0,0 +1,47 @@
# binding
binding.vigicrues.name = Extension VigiCrues
binding.vigicrues.description = Informations de niveau et de seuil d'alerte des rivières de France.
# Station thing config
thing-type.config.vigicrues.station.id.label = Identifiant
thing-type.config.vigicrues.station.id.description = Identifiant unique de la station.
thing-type.config.vigicrues.station.refresh.label = Période de Rafraîchissement
thing-type.config.vigicrues.station.refresh.description = Fréquence de rafraichissement en minutes.
# thing types
thing-type.vigicrues.station.label = Station
thing-type.vigicrues.station.description = Fournit les informations de niveau et de flux pour cette station.
# channel types
channel-type.vigicrues.height.label = Hauteur
channel-type.vigicrues.height.description = Hauteur d'eau dans le cours d'eau.
channel-type.vigicrues.relative-height.label = Hauteur relative
channel-type.vigicrues.relative-height.description = Hauteur relative par rapport aux crues historiques.
channel-type.vigicrues.flow.label = Débit
channel-type.vigicrues.flow.description = Débit du cours d'eau.
channel-type.vigicrues.relative-flow.label = Débit relatif
channel-type.vigicrues.relative-flow.description = Débit relatif par rapport aux crues historiques.
channel-type.vigicrues.alert-level.label = Niveau d'alerte
channel-type.vigicrues.alert-level.state.option.0 = Vert
channel-type.vigicrues.alert-level.state.option.1 = Jaune
channel-type.vigicrues.alert-level.state.option.2 = Orange
channel-type.vigicrues.alert-level.state.option.3 = Rouge
channel-type.vigicrues.alert-icon.label = Pictogramme
channel-type.vigicrues.alert-icon.description = Pictogramme officiel associé au niveau d'alerte.
channel-type.vigicrues.short-comment.label = Situation
channel-type.vigicrues.short-comment.description = Bref descriptif de la situation.
channel-type.vigicrues.comment.label = Commentaire
channel-type.vigicrues.comment.description = Commentaire détaillé.
channel-type.vigicrues.observation-time.label = Horodatage
channel-type.vigicrues.observation-time.description = Heure de rapport des mesures.

View File

@ -6,9 +6,7 @@
<thing-type id="station">
<label>Station</label>
<description>
Provides river level informations for this station
</description>
<description>Provides river level informations for this station</description>
<channels>
<channel id="height" typeId="height"/>
@ -24,11 +22,9 @@
<channel id="alert" typeId="alert-level"/>
<channel id="alert-icon" typeId="alert-icon"/>
<channel id="short-comment" typeId="comment">
<label>Info Qualification</label>
</channel>
<channel id="comment" typeId="comment">
<label>Situation</label>
<label>Short description</label>
</channel>
<channel id="comment" typeId="comment"/>
<channel id="observation-time" typeId="observation-time"/>
</channels>
@ -36,7 +32,7 @@
<config-description>
<parameter name="id" type="text" required="true">
<label>Identifiant</label>
<label>Identifier</label>
<description>Id of the station</description>
</parameter>
<parameter name="refresh" type="integer" min="1" required="true" unit="min">
@ -51,6 +47,10 @@
<item-type>Number:VolumetricFlowRate</item-type>
<label>Current Flow</label>
<category>flow</category>
<tags>
<tag>Measurement</tag>
<tag>Level</tag>
</tags>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
@ -59,6 +59,10 @@
<label>Observation Time</label>
<description>Observation date and time</description>
<category>time</category>
<tags>
<tag>Status</tag>
<tag>Timestamp</tag>
</tags>
<state readOnly="true"/>
</channel-type>
@ -66,38 +70,59 @@
<item-type>Number:Length</item-type>
<label>Height</label>
<description>Water level in the river</description>
<category>flowpipe</category>
<tags>
<tag>Measurement</tag>
<tag>Level</tag>
</tags>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<channel-type id="gauge">
<item-type>Number:Dimensionless</item-type>
<label>Relative Measure</label>
<tags>
<tag>Measurement</tag>
<tag>Level</tag>
</tags>
<state readOnly="true" pattern="%.2f %unit%"/>
</channel-type>
<channel-type id="alert-level">
<item-type>Number</item-type>
<label>Alerte</label>
<label>Alert</label>
<category>error</category>
<tags>
<tag>Alarm</tag>
<tag>Water</tag>
</tags>
<state readOnly="true">
<options>
<option value="0">Vert</option>
<option value="1">Jaune</option>
<option value="0">Green</option>
<option value="1">Yellow</option>
<option value="2">Orange</option>
<option value="3">Rouge</option>
<option value="3">Red</option>
</options>
</state>
</channel-type>
<channel-type id="comment">
<item-type>String</item-type>
<label>Commentaire</label>
<label>Comment</label>
<category>text</category>
<tags>
<tag>Status</tag>
</tags>
<state readOnly="true" pattern="%s"/>
</channel-type>
<channel-type id="alert-icon">
<item-type>Image</item-type>
<label>Pictogramme</label>
<description>Pictogramme associé au niveau d'alerte.</description>
<label>Pictogram</label>
<description>Official pictogram associated to alert level.</description>
<tags>
<tag>Status</tag>
</tags>
<state readOnly="true"/>
</channel-type>
</thing:thing-descriptions>