* Adding localization and a bit of code cleansing.
Signed-off-by: clinique <gael@lhopital.org>
* Review corrections
Signed-off-by: clinique <gael@lhopital.org>
*/
package org.openhab.binding.vigicrues.internal;
-import java.util.Collections;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
@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";
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);
}
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;
@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
}
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);
}
}
}
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);
}
}
super(null, e);
}
- public VigiCruesException(String msg, Throwable cause) {
- super(msg, cause);
- }
-
public VigiCruesException(String msg) {
super(msg, null);
}
@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;
}
}
*/
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;
/**
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;
}
}
} 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)));
}
});
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
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);
}
}
- 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));
}
}
- 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;
}
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>
--- /dev/null
+
+# 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.
+
<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"/>
<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>
<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">
<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>
<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>
<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>