mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[Vigicrues] OH3 enhancements (#8952)
* Staging work Saving my work Vigicrues extensions for OH3 First code review * Code review and some corrections * Code review enhancements Changed alert to Number * Code review corrections * Correcting my error * Adressing SAT finding Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
parent
918408eac1
commit
3a4eaae1e9
@ -23,7 +23,10 @@ Of course, you can add multiple Things, e.g. for getting measures for different
|
||||
|
||||
## Discovery
|
||||
|
||||
This binding does not handle auto-discovery.
|
||||
You can discover stations based upon the system location.
|
||||
Select Vigicrues binding and click scan in order to discover new stations.
|
||||
The first scan will proceed with stations located in a radius of 10 km.
|
||||
This radius will increase by 10 km at each new scan.
|
||||
|
||||
## Binding Configuration
|
||||
|
||||
@ -41,13 +44,31 @@ The thing has a few configuration parameters:
|
||||
|
||||
## Channels
|
||||
|
||||
Once created, at first initialization, the thing will discover its capabilities (available data) using the webservices apis.
|
||||
Channels will be presented depending upon actual available data.
|
||||
|
||||
The VigiCrues information that retrieved are made available with these channels:
|
||||
|
||||
| Channel ID | Item Type | Description |
|
||||
|------------------|---------------------------|-------------------------------|
|
||||
| observation-time | DateTime | Date and time of measurement |
|
||||
| flow | Number:VolumetricFlowRate | Volume of water per time unit |
|
||||
| height | Number:Length | Water height of the river |
|
||||
| Channel ID | Item Type | Description |
|
||||
|------------------|---------------------------|------------------------------------------------------------|
|
||||
| observation-time | DateTime | Date and time of measurement |
|
||||
| flow | Number:VolumetricFlowRate | Volume of water per time unit |
|
||||
| height | Number:Length | Water height of the river |
|
||||
| relative-height | Number:Dimensionless | Current water level toward lowest historical flood |
|
||||
| relative-flow | Number:Dimensionless | Current water flow tower lowest historical flood |
|
||||
| alert (*) | Number | Flooding alert level of the portion related to the station |
|
||||
| alert-icon | Image | Pictogram associated to the alert level |
|
||||
| short-comment | String | Description of the alert level |
|
||||
| comment | String | Detailed informations regarding the ongoing event |
|
||||
|
||||
(*) Each alert level is described by a color :
|
||||
|
||||
| Code | Color | Description |
|
||||
|------|--------|-------------------------------------------|
|
||||
| 0 | Green | No particular vigilance |
|
||||
| 1 | Yellow | Be attentive to the flooding situation |
|
||||
| 2 | Orange | Be "very vigilant" in the concerned areas |
|
||||
| 3 | Red | Absolute vigilance required |
|
||||
|
||||
|
||||
## Full Example
|
||||
|
@ -15,13 +15,15 @@ package org.openhab.binding.vigicrues.internal;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VigiCruesConfiguration} is the class used to match the
|
||||
* The {@link StationConfiguration} is the class used to match the
|
||||
* thing configuration.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VigiCruesConfiguration {
|
||||
public class StationConfiguration {
|
||||
public static String ID = "id";
|
||||
|
||||
public String id = "";
|
||||
public int refresh = 30;
|
||||
}
|
@ -28,17 +28,27 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||
public class VigiCruesBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "vigicrues";
|
||||
public static final String OPENDATASOFT_URL = "https://public.opendatasoft.com/api/records/1.0/search/";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_VIGI_CRUES = new ThingTypeUID(BINDING_ID, "station");
|
||||
public static final ThingTypeUID THING_TYPE_STATION = new ThingTypeUID(BINDING_ID, "station");
|
||||
|
||||
// List of all Channel id's
|
||||
public static final String OBSERVATION_TIME = "observation-time";
|
||||
public static final String HEIGHT = "height";
|
||||
public static final String FLOW = "flow";
|
||||
|
||||
public static final String ALERT = "alert";
|
||||
public static final String COMMENT = "comment";
|
||||
public static final String RELATIVE_PREFIX = "relative";
|
||||
public static final String RELATIVE_HEIGHT = RELATIVE_PREFIX + "-" + HEIGHT;
|
||||
public static final String RELATIVE_FLOW = RELATIVE_PREFIX + "-" + FLOW;
|
||||
public static final String SHORT_COMMENT = "short-" + COMMENT;
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_VIGI_CRUES);
|
||||
// List of properties Labels
|
||||
public static final String TRONCON = "Tronçon";
|
||||
public static final String DISTANCE = "Distance";
|
||||
public static final String RIVER = "Cours";
|
||||
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);
|
||||
}
|
||||
|
@ -12,14 +12,13 @@
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal;
|
||||
|
||||
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.*;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.SUPPORTED_THING_TYPES_UIDS;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.vigicrues.internal.api.ApiHandler;
|
||||
import org.openhab.binding.vigicrues.internal.handler.VigiCruesHandler;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.i18n.LocationProvider;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
@ -29,10 +28,6 @@ import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
|
||||
/**
|
||||
* The {@link VigiCruesHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
@ -42,17 +37,13 @@ import com.google.gson.JsonDeserializer;
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.vigicrues")
|
||||
@NonNullByDefault
|
||||
public class VigiCruesHandlerFactory extends BaseThingHandlerFactory {
|
||||
private final Gson gson;
|
||||
// Needed for converting UTC time to local time
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
private final LocationProvider locationProvider;
|
||||
private final ApiHandler apiHandler;
|
||||
|
||||
@Activate
|
||||
public VigiCruesHandlerFactory(@Reference TimeZoneProvider timeZoneProvider) {
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
this.gson = new GsonBuilder()
|
||||
.registerTypeAdapter(ZonedDateTime.class, (JsonDeserializer<ZonedDateTime>) (json, type,
|
||||
jsonDeserializationContext) -> ZonedDateTime.parse(json.getAsJsonPrimitive().getAsString()))
|
||||
.create();
|
||||
public VigiCruesHandlerFactory(@Reference ApiHandler apiHandler, @Reference LocationProvider locationProvider) {
|
||||
this.locationProvider = locationProvider;
|
||||
this.apiHandler = apiHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -63,11 +54,6 @@ public class VigiCruesHandlerFactory extends BaseThingHandlerFactory {
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(THING_TYPE_VIGI_CRUES)) {
|
||||
return new VigiCruesHandler(thing, timeZoneProvider, gson);
|
||||
}
|
||||
|
||||
return null;
|
||||
return supportsThingType(thingTypeUID) ? new VigiCruesHandler(thing, locationProvider, apiHandler) : null;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.api;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.vigicrues.internal.dto.hubeau.HubEauResponse;
|
||||
import org.openhab.binding.vigicrues.internal.dto.opendatasoft.OpenDatasoftResponse;
|
||||
import org.openhab.binding.vigicrues.internal.dto.vigicrues.CdStationHydro;
|
||||
import org.openhab.binding.vigicrues.internal.dto.vigicrues.InfoVigiCru;
|
||||
import org.openhab.binding.vigicrues.internal.dto.vigicrues.TerEntVigiCru;
|
||||
import org.openhab.binding.vigicrues.internal.dto.vigicrues.TronEntVigiCru;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
import org.openhab.core.library.types.PointType;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link ApiHandler} is the responsible to call a given
|
||||
* url and transform the answer in the appropriate dto class
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
|
||||
@Component(service = ApiHandler.class)
|
||||
@NonNullByDefault
|
||||
public class ApiHandler {
|
||||
private static final int TIMEOUT_MS = 30000;
|
||||
private final Gson gson;
|
||||
|
||||
@Activate
|
||||
public ApiHandler(@Reference TimeZoneProvider timeZoneProvider) {
|
||||
this.gson = new GsonBuilder().registerTypeAdapter(ZonedDateTime.class,
|
||||
(JsonDeserializer<ZonedDateTime>) (json, type, jsonDeserializationContext) -> ZonedDateTime
|
||||
.parse(json.getAsJsonPrimitive().getAsString())
|
||||
.withZoneSameInstant(timeZoneProvider.getTimeZone()))
|
||||
.create();
|
||||
}
|
||||
|
||||
private <T> T execute(String url, Class<T> responseType) throws VigiCruesException {
|
||||
String jsonResponse = "";
|
||||
try {
|
||||
jsonResponse = HttpUtil.executeUrl("GET", url, TIMEOUT_MS);
|
||||
return gson.fromJson(jsonResponse, responseType);
|
||||
} catch (IOException e) {
|
||||
throw new VigiCruesException(e);
|
||||
} catch (JsonSyntaxException e) {
|
||||
throw new VigiCruesException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public InfoVigiCru getTronconStatus(String tronconId) throws VigiCruesException {
|
||||
final String BASE_URL = "https://www.vigicrues.gouv.fr/services/1/InfoVigiCru.jsonld/?TypEntVigiCru=8&CdEntVigiCru=%s";
|
||||
return execute(String.format(BASE_URL, tronconId), InfoVigiCru.class);
|
||||
}
|
||||
|
||||
public TronEntVigiCru getTroncon(String stationId) throws VigiCruesException {
|
||||
final String BASE_URL = "https://www.vigicrues.gouv.fr/services/1/TronEntVigiCru.jsonld/?TypEntVigiCru=8&CdEntVigiCru=%s";
|
||||
return execute(String.format(BASE_URL, stationId), TronEntVigiCru.class);
|
||||
}
|
||||
|
||||
public TerEntVigiCru getTerritoire(String stationId) throws VigiCruesException {
|
||||
final String BASE_URL = "https://www.vigicrues.gouv.fr/services/1/TerEntVigiCru.jsonld/?TypEntVigiCru=5&CdEntVigiCru=%s";
|
||||
return execute(String.format(BASE_URL, stationId), TerEntVigiCru.class);
|
||||
}
|
||||
|
||||
public CdStationHydro getStationDetails(String stationId) throws VigiCruesException {
|
||||
final String BASE_URL = "https://www.vigicrues.gouv.fr/services/station.json/index.php?CdStationHydro=%s";
|
||||
return execute(String.format(BASE_URL, stationId), CdStationHydro.class);
|
||||
}
|
||||
|
||||
public OpenDatasoftResponse getMeasures(String stationId) throws VigiCruesException {
|
||||
final String BASE_URL = "https://public.opendatasoft.com/api/records/1.0/search/?dataset=vigicrues&sort=timestamp&q=%s";
|
||||
return execute(String.format(BASE_URL, stationId), OpenDatasoftResponse.class);
|
||||
}
|
||||
|
||||
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",
|
||||
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);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.api;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.io.net.http.TlsCertificateProvider;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* Provides a TrustManager for the VigiCrues SSL certificate
|
||||
*
|
||||
* @author Gaël L'hopital - Initial Contribution
|
||||
*/
|
||||
@Component
|
||||
@NonNullByDefault
|
||||
public class VigiCruesCertificateProvider implements TlsCertificateProvider {
|
||||
|
||||
@Override
|
||||
public String getHostName() {
|
||||
return "www.vigicrues.gouv.fr";
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getCertificate() {
|
||||
URL resource = Thread.currentThread().getContextClassLoader().getResource("vigicrues.cer");
|
||||
if (resource != null) {
|
||||
return resource;
|
||||
} else {
|
||||
throw new IllegalStateException("Certifcate resource not found or not accessible");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.api;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Exception for errors when using the VigiCrues API
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VigiCruesException extends Exception {
|
||||
private static final long serialVersionUID = -7781683052187130152L;
|
||||
|
||||
public VigiCruesException(Throwable e) {
|
||||
super(null, e);
|
||||
}
|
||||
|
||||
public VigiCruesException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
public VigiCruesException(String msg) {
|
||||
super(msg, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.vigicrues.internal.StationConfiguration;
|
||||
import org.openhab.binding.vigicrues.internal.api.ApiHandler;
|
||||
import org.openhab.binding.vigicrues.internal.api.VigiCruesException;
|
||||
import org.openhab.binding.vigicrues.internal.dto.hubeau.HubEauResponse;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.i18n.LocationProvider;
|
||||
import org.openhab.core.library.types.PointType;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link VigiCruesDiscoveryService} searches for available
|
||||
* hydro stations discoverable through API
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
@Component(service = DiscoveryService.class, configurationPid = "discovery.vigicrues")
|
||||
@NonNullByDefault
|
||||
public class VigiCruesDiscoveryService extends AbstractDiscoveryService {
|
||||
private static final int SEARCH_TIME = 5;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(VigiCruesDiscoveryService.class);
|
||||
private final LocationProvider locationProvider;
|
||||
private final ApiHandler apiHandler;
|
||||
|
||||
private int searchRange = 10;
|
||||
|
||||
@Activate
|
||||
public VigiCruesDiscoveryService(@Reference ApiHandler apiHandler, @Reference LocationProvider locationProvider) {
|
||||
super(SUPPORTED_THING_TYPES_UIDS, SEARCH_TIME, false);
|
||||
this.apiHandler = apiHandler;
|
||||
this.locationProvider = locationProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScan() {
|
||||
PointType location = locationProvider.getLocation();
|
||||
if (location != null) {
|
||||
try {
|
||||
HubEauResponse response = apiHandler.discoverStations(location, searchRange);
|
||||
if (response.count > 0) {
|
||||
response.stations.stream().filter(station -> station.enService).forEach(station -> {
|
||||
thingDiscovered(DiscoveryResultBuilder
|
||||
.create(new ThingUID(THING_TYPE_STATION, station.codeStation))
|
||||
.withLabel(station.libelleStation).withRepresentationProperty(StationConfiguration.ID)
|
||||
.withProperty(StationConfiguration.ID, station.codeStation).build());
|
||||
});
|
||||
} else {
|
||||
logger.info("No station exists in a neighbourhood of {} km", searchRange);
|
||||
}
|
||||
} catch (VigiCruesException e) {
|
||||
logger.warn("Error discovering nearby hydro stations : {}", e.getMessage());
|
||||
}
|
||||
searchRange += 10;
|
||||
}
|
||||
stopScan();
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
package org.openhab.binding.vigicrues.internal.dto.hubeau;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class HubEauResponse {
|
||||
public class StationData {
|
||||
@SerializedName("en_service")
|
||||
public boolean enService;
|
||||
|
||||
@SerializedName("code_station")
|
||||
public String codeStation;
|
||||
|
||||
@SerializedName("libelle_station")
|
||||
public String libelleStation;
|
||||
|
||||
@SerializedName("longitude_station")
|
||||
public double longitudeStation;
|
||||
|
||||
@SerializedName("latitude_station")
|
||||
public double latitudeStation;
|
||||
|
||||
@SerializedName("libelle_cours_eau")
|
||||
public String libelleCoursEau;
|
||||
/*
|
||||
* Currently unused, maybe interesting in the future
|
||||
*
|
||||
* @SerializedName("code_site")
|
||||
* public String codeSite;
|
||||
*
|
||||
* @SerializedName("libelle_site")
|
||||
* public String libelleSite;
|
||||
*
|
||||
* @SerializedName("type_station")
|
||||
* public String typeStation;
|
||||
*
|
||||
* @SerializedName("coordonnee_x_station")
|
||||
* public int coordonneeXStation;
|
||||
*
|
||||
* @SerializedName("coordonnee_y_station")
|
||||
* public int coordonneeYStation;
|
||||
*
|
||||
* @SerializedName("code_projection")
|
||||
* public int codeProjection;
|
||||
*
|
||||
* @SerializedName("influence_locale_station")
|
||||
* public int influenceLocaleStation;
|
||||
*
|
||||
* @SerializedName("commentaire_station")
|
||||
* public String commentaireStation;
|
||||
*
|
||||
* @SerializedName("altitude_ref_alti_station")
|
||||
* public double altitudeRefAltiStation;
|
||||
*
|
||||
* @SerializedName("code_systeme_alti_site")
|
||||
* public int codeSystemeAltiSite;
|
||||
*
|
||||
* @SerializedName("code_commune_station")
|
||||
* public String codeCommuneStation;
|
||||
*
|
||||
* @SerializedName("libelle_commune")
|
||||
* public String libelleCommune;
|
||||
*
|
||||
* @SerializedName("code_departement")
|
||||
* public String codeDepartement;
|
||||
*
|
||||
* @SerializedName("code_region")
|
||||
* public String codeRegion;
|
||||
*
|
||||
* @SerializedName("libelle_region")
|
||||
* public String libelleRegion;
|
||||
*
|
||||
* @SerializedName("code_cours_eau")
|
||||
* public String codeCoursEau;
|
||||
*
|
||||
* @SerializedName("uri_cours_eau")
|
||||
* public String uriCoursEau;
|
||||
*
|
||||
* @SerializedName("descriptif_station")
|
||||
* public String descriptifStation;
|
||||
*
|
||||
* @SerializedName("date_maj_station")
|
||||
* public String dateMajStation;
|
||||
*
|
||||
* @SerializedName("date_ouverture_station")
|
||||
* public String dateOuvertureStation;
|
||||
*
|
||||
* @SerializedName("date_fermeture_station")
|
||||
* public String dateFermetureStation;
|
||||
*
|
||||
* @SerializedName("commentaire_influence_locale_station")
|
||||
* public String commentaireInfluenceLocaleStation;
|
||||
*
|
||||
* @SerializedName("code_regime_station")
|
||||
* public int codeRegimeStation;
|
||||
*
|
||||
* @SerializedName("qualification_donnees_station")
|
||||
* public int qualificationDonneesStation;
|
||||
*
|
||||
* @SerializedName("code_finalite_station")
|
||||
* public int codeFinaliteStation;
|
||||
*
|
||||
* @SerializedName("type_contexte_loi_stat_station")
|
||||
* public int typeContexteLoiStatStation;
|
||||
*
|
||||
* @SerializedName("type_loi_station")
|
||||
* public int typeLoiStation;
|
||||
*
|
||||
* @SerializedName("code_sandre_reseau_station")
|
||||
* public List<String> codeSandreReseauStation;
|
||||
*
|
||||
* @SerializedName("date_debut_ref_alti_station")
|
||||
* public String dateDebutRefAltiStation;
|
||||
*
|
||||
* @SerializedName("date_activation_ref_alti_station")
|
||||
* public String dateActivationRefAltiStation;
|
||||
*
|
||||
* @SerializedName("date_maj_ref_alti_station")
|
||||
* public String dateMajRefAltiStation;
|
||||
*
|
||||
* @SerializedName("libelle_departement")
|
||||
* public String libelleDepartement;
|
||||
* public Geometry geometry;
|
||||
*/
|
||||
}
|
||||
|
||||
public int count;
|
||||
@SerializedName("data")
|
||||
public List<StationData> stations;
|
||||
|
||||
/*
|
||||
* Currently unused, maybe interesting in the future
|
||||
* public String first;
|
||||
* public String last;
|
||||
* public String prev;
|
||||
* public String next;
|
||||
*
|
||||
* @SerializedName("api_version")
|
||||
* public String apiVersion;
|
||||
*
|
||||
* public class Crs {
|
||||
* public String type;
|
||||
* public Properties properties;
|
||||
* }
|
||||
*
|
||||
* public class Properties {
|
||||
* public String name;
|
||||
* }
|
||||
*
|
||||
* public class Geometry {
|
||||
* public String type;
|
||||
* public Crs crs;
|
||||
* public List<Double> coordinates;
|
||||
* }
|
||||
*/
|
||||
}
|
@ -10,8 +10,10 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.json;
|
||||
package org.openhab.binding.vigicrues.internal.dto.opendatasoft;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -30,7 +32,7 @@ public class OpenDatasoftResponse {
|
||||
@SerializedName("nhits")
|
||||
private int nHits;
|
||||
private @Nullable Parameters parameters;
|
||||
private Record[] records = {};
|
||||
private List<Record> records = new ArrayList<>();
|
||||
|
||||
public int getNHits() {
|
||||
return nHits;
|
||||
@ -44,7 +46,7 @@ public class OpenDatasoftResponse {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public Record[] getRecords() {
|
||||
return records;
|
||||
public Optional<VigiCruesFields> getFirstRecord() {
|
||||
return records.stream().findFirst().flatMap(Record::getFields);
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.json;
|
||||
package org.openhab.binding.vigicrues.internal.dto.opendatasoft;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.util.Arrays;
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.json;
|
||||
package org.openhab.binding.vigicrues.internal.dto.opendatasoft;
|
||||
|
||||
import java.util.Optional;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.json;
|
||||
package org.openhab.binding.vigicrues.internal.dto.opendatasoft;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.json;
|
||||
package org.openhab.binding.vigicrues.internal.dto.opendatasoft;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.dto.vigicrues;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* The {@link CdStationHydro} is the Java class used to map the JSON
|
||||
* response to an vigicrue api endpoint request.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
public class CdStationHydro {
|
||||
|
||||
public class PereBoitEntVigiCru {
|
||||
@SerializedName("CdEntVigiCru")
|
||||
public String cdEntVigiCru;
|
||||
}
|
||||
|
||||
public class CruesHistorique {
|
||||
@SerializedName("LbUsuel")
|
||||
public String name;
|
||||
@SerializedName("ValHauteur")
|
||||
public double height;
|
||||
@SerializedName("ValDebit")
|
||||
public 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));
|
||||
}
|
||||
if (flow != 0) {
|
||||
result.put(String.format("%s %s (%s)", VigiCruesBindingConstants.FLOOD, VigiCruesBindingConstants.FLOW,
|
||||
name), String.format(Locale.US, "%.2f m³/s", flow));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class VigilanceCrues {
|
||||
@SerializedName("PereBoitEntVigiCru")
|
||||
public PereBoitEntVigiCru pereBoitEntVigiCru;
|
||||
@SerializedName("CruesHistoriques")
|
||||
public List<CruesHistorique> cruesHistoriques;
|
||||
/*
|
||||
* Currently unused, maybe interesting in the future
|
||||
*
|
||||
* @SerializedName("StationPrevision")
|
||||
* public String stationPrevision;
|
||||
*
|
||||
* @SerializedName("Photo")
|
||||
* public String photo;
|
||||
*
|
||||
* @SerializedName("ZoomInitial")
|
||||
* public String zoomInitial;
|
||||
*/
|
||||
}
|
||||
|
||||
@SerializedName("VigilanceCrues")
|
||||
public VigilanceCrues vigilanceCrues;
|
||||
/*
|
||||
* Currently unused, maybe interesting in the future
|
||||
*
|
||||
* @SerializedName("VersionFlux")
|
||||
* public String versionFlux;
|
||||
*
|
||||
* @SerializedName("CdStationHydro")
|
||||
* public String cdStationHydro;
|
||||
*
|
||||
* @SerializedName("LbStationHydro")
|
||||
* public String lbStationHydro;
|
||||
*
|
||||
* @SerializedName("LbCoursEau")
|
||||
* public String lbCoursEau;
|
||||
*
|
||||
* @SerializedName("CdStationHydroAncienRef")
|
||||
* public String cdStationHydroAncienRef;
|
||||
*
|
||||
* @SerializedName("CdCommune")
|
||||
* public String cdCommune;
|
||||
*
|
||||
* @SerializedName("error_msg")
|
||||
* public String errorMsg;
|
||||
*/
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.dto.vigicrues;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link InfoVigiCru} is the Java class used to map the JSON
|
||||
* response to an vigicrue api endpoint request.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
public class InfoVigiCru {
|
||||
public class VicInfoVigiCru {
|
||||
@SerializedName("vic:NivInfoVigiCru")
|
||||
public int vicNivInfoVigiCru;
|
||||
@SerializedName("vic:SituActuInfoVigiCru")
|
||||
public String vicSituActuInfoVigiCru;
|
||||
@SerializedName("vic:QualifInfoVigiCru")
|
||||
public String vicQualifInfoVigiCru;
|
||||
/*
|
||||
* Currently unused, maybe interesting in the future
|
||||
*
|
||||
* @SerializedName("vic:RefInfoVigiCru")
|
||||
* private String vicRefInfoVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:TypInfoVigiCru")
|
||||
* private int vicTypInfoVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:DtHrInfoVigiCru")
|
||||
* private String vicDtHrInfoVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:DtHrSuivInfoVigiCru")
|
||||
* private String vicDtHrSuivInfoVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:EstNivCalInfoVigiCru")
|
||||
* private Boolean vicEstNivCalInfoVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:StInfoVigiCru")
|
||||
* private int vicStInfoVigiCru;
|
||||
*/
|
||||
}
|
||||
|
||||
@SerializedName("vic:InfoVigiCru")
|
||||
public VicInfoVigiCru vicInfoVigiCru;
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.dto.vigicrues;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link TerEntVigiCru} is the Java class used to map the JSON
|
||||
* response to an vigicrue api endpoint request.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
public class TerEntVigiCru {
|
||||
|
||||
public class VicTerEntVigiCru {
|
||||
@SerializedName("vic:aNMoinsUn")
|
||||
public List<VicANMoinsUn> vicANMoinsUn;
|
||||
/*
|
||||
* Currently unused, maybe interesting in the future
|
||||
*
|
||||
* @SerializedName("@id")
|
||||
* public String id;
|
||||
*
|
||||
* @SerializedName("vic:CdEntVigiCru")
|
||||
* public String vicCdEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:TypEntVigiCru")
|
||||
* public String vicTypEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:LbEntVigiCru")
|
||||
* public String vicLbEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:DtHrCreatEntVigiCru")
|
||||
* public String vicDtHrCreatEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:DtHrMajEntVigiCru")
|
||||
* public String vicDtHrMajEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:StEntVigiCru")
|
||||
* public String vicStEntVigiCru;
|
||||
* public int count_aNMoinsUn;
|
||||
*
|
||||
* @SerializedName("LinkInfoCru")
|
||||
* public String linkInfoCru;
|
||||
*/
|
||||
}
|
||||
|
||||
@SerializedName("vic:TerEntVigiCru")
|
||||
public VicTerEntVigiCru vicTerEntVigiCru;
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.dto.vigicrues;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link TronEntVigiCru} is the Java class used to map the JSON
|
||||
* response to an vigicrue api endpoint request.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
public class TronEntVigiCru {
|
||||
public class VicStaEntVigiCru {
|
||||
@SerializedName("vic:CdEntVigiCru")
|
||||
public String vicCdEntVigiCru;
|
||||
}
|
||||
|
||||
public class VicTronEntVigiCru {
|
||||
@SerializedName("vic:aNMoinsUn")
|
||||
public List<VicStaEntVigiCru> stations;
|
||||
/*
|
||||
* Currently unused, maybe interesting in the future
|
||||
*
|
||||
* @SerializedName("@id")
|
||||
* public String id;
|
||||
*
|
||||
* @SerializedName("vic:CdEntVigiCru")
|
||||
* public String vicCdEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:TypEntVigiCru")
|
||||
* public String vicTypEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:LbEntVigiCru")
|
||||
* public String vicLbEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:DtHrCreatEntVigiCru")
|
||||
* public String vicDtHrCreatEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:DtHrMajEntVigiCru")
|
||||
* public String vicDtHrMajEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic:StEntVigiCru")
|
||||
* public String vicStEntVigiCru;
|
||||
*
|
||||
* @SerializedName("count_aNPlusUn")
|
||||
* public Integer countANPlusUn;
|
||||
*
|
||||
* @SerializedName("count_aNMoinsUn")
|
||||
* public Integer countANMoinsUn;
|
||||
*
|
||||
* @SerializedName("LinkInfoCru")
|
||||
* public String linkInfoCru;
|
||||
*/
|
||||
}
|
||||
|
||||
@SerializedName("vic:TronEntVigiCru")
|
||||
private VicTronEntVigiCru tronTerEntVigiCru;
|
||||
|
||||
public Stream<VicStaEntVigiCru> getStations() {
|
||||
if (tronTerEntVigiCru != null && tronTerEntVigiCru.stations != null) {
|
||||
return tronTerEntVigiCru.stations.stream();
|
||||
} else {
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.vigicrues.internal.dto.vigicrues;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link VicANMoinsUn} is the Java class used to map the JSON
|
||||
* response to an vigicrue api endpoint request.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
public class VicANMoinsUn {
|
||||
@SerializedName("vic.CdEntVigiCru")
|
||||
public String vicCdEntVigiCru;
|
||||
|
||||
/*
|
||||
* Currently unused, maybe interesting in the future
|
||||
*
|
||||
* @SerializedName("@id")
|
||||
* private String id;
|
||||
*
|
||||
* @SerializedName("vic.TypEntVigiCru")
|
||||
* private String vicTypEntVigiCru;
|
||||
*
|
||||
* @SerializedName("vic.LbEntVigiCru")
|
||||
* private String vicLbEntVigiCru;
|
||||
*
|
||||
* @SerializedName("LinkEntity")
|
||||
* private String linkEntity;
|
||||
*
|
||||
* @SerializedName("LinkInfoCru")
|
||||
* private String linkInfoCru;
|
||||
*/
|
||||
}
|
@ -13,39 +13,55 @@
|
||||
package org.openhab.binding.vigicrues.internal.handler;
|
||||
|
||||
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.*;
|
||||
import static org.openhab.core.library.unit.SmartHomeUnits.CUBICMETRE_PER_SECOND;
|
||||
import static tec.uom.se.unit.Units.METRE;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.io.InputStream;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.vigicrues.internal.VigiCruesConfiguration;
|
||||
import org.openhab.binding.vigicrues.internal.json.OpenDatasoftResponse;
|
||||
import org.openhab.binding.vigicrues.internal.json.Record;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
import org.openhab.binding.vigicrues.internal.StationConfiguration;
|
||||
import org.openhab.binding.vigicrues.internal.api.ApiHandler;
|
||||
import org.openhab.binding.vigicrues.internal.api.VigiCruesException;
|
||||
import org.openhab.binding.vigicrues.internal.dto.hubeau.HubEauResponse;
|
||||
import org.openhab.binding.vigicrues.internal.dto.opendatasoft.OpenDatasoftResponse;
|
||||
import org.openhab.binding.vigicrues.internal.dto.vigicrues.CdStationHydro;
|
||||
import org.openhab.binding.vigicrues.internal.dto.vigicrues.InfoVigiCru;
|
||||
import org.openhab.binding.vigicrues.internal.dto.vigicrues.TerEntVigiCru;
|
||||
import org.openhab.binding.vigicrues.internal.dto.vigicrues.TronEntVigiCru;
|
||||
import org.openhab.binding.vigicrues.internal.dto.vigicrues.VicANMoinsUn;
|
||||
import org.openhab.core.i18n.LocationProvider;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.PointType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.RawType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* The {@link VigiCruesHandler} is responsible for querying the API and
|
||||
* updating channels
|
||||
@ -54,35 +70,124 @@ import com.google.gson.Gson;
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VigiCruesHandler extends BaseThingHandler {
|
||||
private static final String URL = OPENDATASOFT_URL + "?dataset=vigicrues&sort=timestamp&q=";
|
||||
private static final int TIMEOUT_MS = 30000;
|
||||
private final Logger logger = LoggerFactory.getLogger(VigiCruesHandler.class);
|
||||
private final LocationProvider locationProvider;
|
||||
|
||||
// Time zone provider representing time zone configured in openHAB configuration
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
private final Gson gson;
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
private @Nullable String queryUrl;
|
||||
private final ApiHandler apiHandler;
|
||||
|
||||
public VigiCruesHandler(Thing thing, TimeZoneProvider timeZoneProvider, Gson gson) {
|
||||
private List<QuantityType<?>> referenceHeights = new ArrayList<>();
|
||||
private List<QuantityType<?>> referenceFlows = new ArrayList<>();
|
||||
private @Nullable String portion;
|
||||
|
||||
public VigiCruesHandler(Thing thing, LocationProvider locationProvider, ApiHandler apiHandler) {
|
||||
super(thing);
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
this.gson = gson;
|
||||
this.apiHandler = apiHandler;
|
||||
this.locationProvider = locationProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing VigiCrues handler.");
|
||||
|
||||
VigiCruesConfiguration config = getConfigAs(VigiCruesConfiguration.class);
|
||||
logger.debug("config station = {}", config.id);
|
||||
StationConfiguration config = getConfigAs(StationConfiguration.class);
|
||||
logger.debug("config refresh = {} min", config.refresh);
|
||||
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
queryUrl = URL + config.id;
|
||||
|
||||
if (thing.getProperties().isEmpty()) {
|
||||
Map<String, String> properties = discoverAttributes(config);
|
||||
updateProperties(properties);
|
||||
}
|
||||
getReferences();
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(this::updateAndPublish, 0, config.refresh, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
private void getReferences() {
|
||||
List<QuantityType<?>> heights = new ArrayList<>();
|
||||
List<QuantityType<?>> flows = new ArrayList<>();
|
||||
thing.getProperties().keySet().stream().filter(key -> key.startsWith(FLOOD)).forEach(key -> {
|
||||
String value = thing.getProperties().get(key);
|
||||
if (key.contains(FLOW)) {
|
||||
flows.add(new QuantityType<>(value));
|
||||
} else {
|
||||
heights.add(new QuantityType<>(value));
|
||||
}
|
||||
});
|
||||
referenceHeights = heights.stream().distinct().sorted().collect(Collectors.toList());
|
||||
referenceFlows = flows.stream().distinct().sorted().collect(Collectors.toList());
|
||||
portion = thing.getProperties().get(TRONCON);
|
||||
}
|
||||
|
||||
private Map<String, String> discoverAttributes(StationConfiguration config) {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
|
||||
ThingBuilder thingBuilder = editThing();
|
||||
List<Channel> channels = new ArrayList<>(getThing().getChannels());
|
||||
|
||||
try {
|
||||
HubEauResponse stationDetails = apiHandler.discoverStations(config.id);
|
||||
stationDetails.stations.stream().findFirst().ifPresent(station -> {
|
||||
PointType stationLocation = new PointType(
|
||||
String.format(Locale.US, "%f,%f", station.latitudeStation, station.longitudeStation));
|
||||
properties.put(LOCATION, stationLocation.toString());
|
||||
PointType serverLocation = locationProvider.getLocation();
|
||||
if (serverLocation != null) {
|
||||
DecimalType distance = serverLocation.distanceFrom(stationLocation);
|
||||
properties.put(DISTANCE, new QuantityType<>(distance, SIUnits.METRE).toString());
|
||||
}
|
||||
properties.put(RIVER, station.libelleCoursEau);
|
||||
});
|
||||
} catch (VigiCruesException e) {
|
||||
logger.info("Unable to retrieve station location details {} : {}", config.id, e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
CdStationHydro refineStation = apiHandler.getStationDetails(config.id);
|
||||
if (refineStation.vigilanceCrues.cruesHistoriques == null) {
|
||||
throw new VigiCruesException("No historical data available");
|
||||
}
|
||||
refineStation.vigilanceCrues.cruesHistoriques.stream()
|
||||
.forEach(crue -> properties.putAll(crue.getDescription()));
|
||||
String codeTerritoire = refineStation.vigilanceCrues.pereBoitEntVigiCru.cdEntVigiCru;
|
||||
TerEntVigiCru territoire = apiHandler.getTerritoire(codeTerritoire);
|
||||
for (VicANMoinsUn troncon : territoire.vicTerEntVigiCru.vicANMoinsUn) {
|
||||
TronEntVigiCru detail = apiHandler.getTroncon(troncon.vicCdEntVigiCru);
|
||||
if (detail.getStations().anyMatch(s -> config.id.equalsIgnoreCase(s.vicCdEntVigiCru))) {
|
||||
properties.put(TRONCON, troncon.vicCdEntVigiCru);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (VigiCruesException e) {
|
||||
logger.info("Historical flooding data are not available {} : {}", config.id, e.getMessage());
|
||||
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)));
|
||||
}
|
||||
|
||||
try {
|
||||
OpenDatasoftResponse measures = apiHandler.getMeasures(config.id);
|
||||
measures.getFirstRecord().ifPresent(field -> {
|
||||
if (field.getHeight().isEmpty()) {
|
||||
channels.removeIf(channel -> (channel.getUID().getId().contains(HEIGHT)));
|
||||
}
|
||||
if (field.getFlow().isEmpty()) {
|
||||
channels.removeIf(channel -> (channel.getUID().getId().contains(FLOW)));
|
||||
}
|
||||
});
|
||||
} catch (VigiCruesException e) {
|
||||
logger.warn("Unable to read measurements data {} : {}", config.id, e.getMessage());
|
||||
}
|
||||
|
||||
thingBuilder.withChannels(channels);
|
||||
updateThing(thingBuilder.build());
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Disposing the VigiCrues handler.");
|
||||
@ -102,26 +207,43 @@ public class VigiCruesHandler extends BaseThingHandler {
|
||||
}
|
||||
|
||||
private void updateAndPublish() {
|
||||
StationConfiguration config = getConfigAs(StationConfiguration.class);
|
||||
try {
|
||||
if (queryUrl != null) {
|
||||
String response = HttpUtil.executeUrl("GET", queryUrl, TIMEOUT_MS);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
OpenDatasoftResponse apiResponse = gson.fromJson(response, OpenDatasoftResponse.class);
|
||||
Arrays.stream(apiResponse.getRecords()).findFirst().flatMap(Record::getFields).ifPresent(field -> {
|
||||
field.getHeight().ifPresent(height -> updateQuantity(HEIGHT, height, METRE));
|
||||
field.getFlow().ifPresent(flow -> updateQuantity(FLOW, flow, CUBICMETRE_PER_SECOND));
|
||||
field.getTimestamp().ifPresent(date -> updateDate(OBSERVATION_TIME, date));
|
||||
OpenDatasoftResponse measures = apiHandler.getMeasures(config.id);
|
||||
measures.getFirstRecord().ifPresent(field -> {
|
||||
field.getHeight().ifPresent(height -> {
|
||||
updateQuantity(HEIGHT, height, SIUnits.METRE);
|
||||
updateRelativeMeasure(RELATIVE_HEIGHT, referenceHeights, height);
|
||||
});
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DISABLED,
|
||||
"queryUrl should never be null, but it is !");
|
||||
field.getFlow().ifPresent(flow -> {
|
||||
updateQuantity(FLOW, flow, SmartHomeUnits.CUBICMETRE_PER_SECOND);
|
||||
updateRelativeMeasure(RELATIVE_FLOW, referenceFlows, flow);
|
||||
});
|
||||
field.getTimestamp().ifPresent(date -> updateDate(OBSERVATION_TIME, date));
|
||||
});
|
||||
String currentPortion = this.portion;
|
||||
if (currentPortion != null) {
|
||||
InfoVigiCru status = apiHandler.getTronconStatus(currentPortion);
|
||||
updateAlert(ALERT, status.vicInfoVigiCru.vicNivInfoVigiCru - 1);
|
||||
updateString(SHORT_COMMENT, status.vicInfoVigiCru.vicSituActuInfoVigiCru);
|
||||
updateString(COMMENT, status.vicInfoVigiCru.vicQualifInfoVigiCru);
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
String.format("Querying '%s' raised : %s", queryUrl, e.getMessage()));
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
String.format("Error opening connection to VigiCrues webservice : {}", e.getMessage()));
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (VigiCruesException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateString(String channelId, String value) {
|
||||
if (isLinked(channelId)) {
|
||||
updateState(channelId, new StringType(value));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRelativeMeasure(String channelId, List<QuantityType<?>> reference, double value) {
|
||||
if (reference.size() > 0) {
|
||||
double percent = value / reference.get(0).doubleValue() * 100;
|
||||
updateQuantity(channelId, percent, SmartHomeUnits.PERCENT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,8 +255,27 @@ public class VigiCruesHandler extends BaseThingHandler {
|
||||
|
||||
public void updateDate(String channelId, ZonedDateTime zonedDateTime) {
|
||||
if (isLinked(channelId)) {
|
||||
ZonedDateTime localDateTime = zonedDateTime.withZoneSameInstant(timeZoneProvider.getTimeZone());
|
||||
updateState(channelId, new DateTimeType(localDateTime));
|
||||
updateState(channelId, new DateTimeType(zonedDateTime));
|
||||
}
|
||||
}
|
||||
|
||||
public void updateAlert(String channelId, int value) {
|
||||
String channelIcon = channelId + "-icon";
|
||||
if (isLinked(channelId)) {
|
||||
updateState(channelId, new DecimalType(value));
|
||||
}
|
||||
if (isLinked(channelIcon)) {
|
||||
byte[] resource = getResource(String.format("picto/crue-%d.svg", value));
|
||||
updateState(channelIcon, resource != null ? new RawType(resource, "image/svg+xml") : UnDefType.UNDEF);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,28 @@
|
||||
|
||||
<channels>
|
||||
<channel id="height" typeId="height"/>
|
||||
<channel id="relative-height" typeId="gauge">
|
||||
<label>Relative Height</label>
|
||||
<description>Current height toward historical floods.</description>
|
||||
</channel>
|
||||
<channel id="flow" typeId="flow"/>
|
||||
<channel id="relative-flow" typeId="gauge">
|
||||
<label>Relative Flow</label>
|
||||
<description>Current flow toward historic floods.</description>
|
||||
</channel>
|
||||
<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>
|
||||
</channel>
|
||||
<channel id="observation-time" typeId="observation-time"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>id</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="id" type="text" required="true">
|
||||
<label>Identifiant</label>
|
||||
@ -32,6 +50,7 @@
|
||||
<channel-type id="flow">
|
||||
<item-type>Number:VolumetricFlowRate</item-type>
|
||||
<label>Current Flow</label>
|
||||
<category>flow</category>
|
||||
<state readOnly="true" pattern="%.2f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
@ -39,6 +58,7 @@
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Observation Time</label>
|
||||
<description>Observation date and time</description>
|
||||
<category>time</category>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
@ -48,4 +68,36 @@
|
||||
<description>Water level in the river</description>
|
||||
<state readOnly="true" pattern="%.2f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="gauge">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Relative Measure</label>
|
||||
<state readOnly="true" pattern="%.2f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="alert-level">
|
||||
<item-type>Number</item-type>
|
||||
<label>Alerte</label>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="0">Vert</option>
|
||||
<option value="1">Jaune</option>
|
||||
<option value="2">Orange</option>
|
||||
<option value="3">Rouge</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="comment">
|
||||
<item-type>String</item-type>
|
||||
<label>Commentaire</label>
|
||||
<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>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
|
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 78.271 84.645"><g id="indice-vert"><path d="M47.594 24.86c0 .233-.197.944-.59 2.123a480.704 480.704 0 0 1-2.656 7.733c-.432 1.22-.689 2.027-.77 2.421a89.557 89.557 0 0 1-1.414 4.134 133.507 133.507 0 0 0-1.533 4.367 82.549 82.549 0 0 1-1.42 4.311 678.77 678.77 0 0 0-1.533 4.307c-.316.869-.65 1.828-1.004 2.891a54.563 54.563 0 0 1-1.004 2.775 481.208 481.208 0 0 1-2.125 5.963 97.792 97.792 0 0 0-2.006 6.08c-.475 1.42-.943 2.5-1.418 3.246-.473.75-1.004 1.277-1.594 1.596-.592.313-1.281.49-2.064.531-.791.039-1.656.057-2.602.057-1.258 0-2.301-.039-3.125-.117-.828-.08-1.535-.371-2.127-.885-.59-.512-1.141-1.279-1.654-2.303-.51-1.021-1.043-2.479-1.596-4.369a710.439 710.439 0 0 0-7.375-21.898A1676.56 1676.56 0 0 1 .369 25.92a1.32 1.32 0 0 1-.119-.589v-.471c0-.787.193-1.379.592-1.773a2.828 2.828 0 0 1 1.416-.77 8.273 8.273 0 0 1 1.713-.175H7.69a4.96 4.96 0 0 1 2.008.415c.627.274 1.197.747 1.709 1.415.514.668.924 1.636 1.24 2.892.158.554.414 1.379.768 2.479.356 1.105.648 2.087.885 2.952a114.139 114.139 0 0 1 1.773 5.611 410.58 410.58 0 0 0 1.887 6.312c.315.871.631 1.873.947 3.014.31 1.141.666 2.264 1.06 3.365.078.234.217.725.412 1.477.197.746.473 1.514.826 2.301.356.785.75 1.494 1.182 2.121.432.633.967.947 1.596.947.551 0 1.059-.314 1.533-.947.473-.627.885-1.314 1.24-2.064.353-.744.629-1.455.826-2.123.195-.666.297-1.041.297-1.123.234-.863.51-1.828.824-2.891.313-1.063.592-2.025.826-2.893a71.07 71.07 0 0 0 .828-2.361c.313-.946.59-1.85.824-2.716.633-1.811 1.262-3.7 1.893-5.666a170.943 170.943 0 0 0 1.889-6.378c.391-1.493.783-2.654 1.178-3.483.395-.825.865-1.433 1.416-1.829.553-.393 1.223-.628 2.008-.706a29.256 29.256 0 0 1 2.832-.119h1.479c.59 0 1.16.077 1.711.235a3.584 3.584 0 0 1 1.418.768c.391.355.589.926.589 1.713z" fill="#28d761" stroke="#504d49" stroke-width=".5"/><path d="M78.271 77.531c0 3.926-9.189 7.113-20.523 7.113-11.336 0-20.523-3.188-20.523-7.113 0-3.928 9.187-7.109 20.523-7.109 11.334 0 20.523 3.182 20.523 7.109z" fill="#7c9fbb"/><ellipse cx="62.657" cy="78.139" rx="9.595" ry="2.639" fill="#63839b"/><path d="M62.656 16.214c0 .048-.053.154-.15.313a.903.903 0 0 1-.459.354c-.545.246-1.17.382-1.885.407-.715.025-1.445.036-2.189.036-.547 0-1.121-.007-1.732-.018a8.751 8.751 0 0 1-1.732-.203 1.903 1.903 0 0 1-.865-.425c-.238-.212-.355-.366-.355-.464V1.072c0-.05.049-.148.152-.293.102-.15.254-.276.457-.372.543-.248 1.189-.375 1.934-.388C56.578.004 57.293 0 57.973 0c.473 0 1.033.004 1.68.019.645.013 1.273.079 1.883.203.342.072.613.208.816.407.207.198.305.345.305.443v15.142zM62.656 36.682c0 .051-.053.157-.15.316a.89.89 0 0 1-.459.35c-.545.249-1.17.385-1.885.41-.715.022-1.445.035-2.189.035-.547 0-1.121-.005-1.732-.017a8.679 8.679 0 0 1-1.732-.202 1.869 1.869 0 0 1-.865-.428c-.238-.21-.355-.364-.355-.464v-15.14c0-.049.049-.147.152-.295a1.16 1.16 0 0 1 .457-.371c.543-.246 1.189-.375 1.934-.389a102.378 102.378 0 0 1 3.823 0c.645.014 1.273.08 1.883.205.342.073.613.209.816.407.207.195.305.346.305.443v15.14zM62.656 57.152c0 .047-.053.154-.15.314a.905.905 0 0 1-.459.352c-.545.246-1.17.383-1.885.408a74.944 74.944 0 0 1-3.921.017 8.603 8.603 0 0 1-1.732-.205 1.89 1.89 0 0 1-.865-.422c-.238-.213-.355-.367-.355-.465V42.013c0-.05.049-.15.152-.296.102-.15.254-.273.457-.373.543-.247 1.189-.376 1.934-.39.748-.012 1.463-.018 2.143-.018.473 0 1.033.006 1.68.018.645.014 1.273.082 1.883.205.342.072.613.208.816.407.207.198.305.345.305.446v15.14z" fill="#504d49"/><path d="M62.656 77.389c0 .051-.053.156-.15.314a.897.897 0 0 1-.459.357c-.545.244-1.17.379-1.885.404a67.95 67.95 0 0 1-3.921.019 8.751 8.751 0 0 1-1.732-.203 1.878 1.878 0 0 1-.865-.428c-.238-.211-.355-.363-.355-.465V62.252c0-.049.049-.148.152-.297.102-.15.254-.273.457-.371.543-.246 1.189-.375 1.934-.389.748-.012 1.463-.018 2.143-.018.473 0 1.033.006 1.68.018.645.014 1.273.08 1.883.205.342.072.613.209.816.404.207.199.305.348.305.447v15.138z" fill="#28d761" stroke="#504d49" stroke-width=".5"/></g></svg>
|
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 78.271 84.645"><g id="indice-jaune"><path d="M47.594 24.86c0 .233-.197.944-.59 2.123a480.704 480.704 0 0 1-2.656 7.733c-.432 1.22-.689 2.027-.77 2.421a89.557 89.557 0 0 1-1.414 4.134 133.507 133.507 0 0 0-1.533 4.367 81.616 81.616 0 0 1-1.42 4.311 831.628 831.628 0 0 0-1.533 4.307c-.316.869-.649 1.828-1.004 2.891s-.692 1.992-1.004 2.775a481.208 481.208 0 0 1-2.125 5.963 98.462 98.462 0 0 0-2.006 6.08c-.475 1.42-.943 2.5-1.418 3.246-.473.75-1.004 1.277-1.594 1.596-.592.313-1.281.49-2.064.531-.791.039-1.656.057-2.602.057-1.258 0-2.301-.039-3.125-.117-.828-.08-1.535-.371-2.127-.885-.59-.512-1.141-1.279-1.653-2.303-.511-1.021-1.044-2.479-1.596-4.369a707.767 707.767 0 0 0-7.376-21.898A1691.504 1691.504 0 0 1 .369 25.92a1.32 1.32 0 0 1-.119-.589v-.471c0-.787.194-1.379.592-1.773a2.828 2.828 0 0 1 1.416-.77 8.273 8.273 0 0 1 1.713-.175H7.69a4.96 4.96 0 0 1 2.008.415c.627.274 1.197.747 1.71 1.415.513.668.923 1.636 1.239 2.892.158.554.414 1.379.769 2.479a72.92 72.92 0 0 1 .884 2.952 114.043 114.043 0 0 1 1.774 5.611c.63 2.164 1.258 4.271 1.888 6.312.313.871.63 1.873.946 3.014a45.059 45.059 0 0 0 1.062 3.365c.077.234.216.725.412 1.477.196.746.472 1.514.826 2.301.354.785.75 1.494 1.182 2.121.431.633.966.947 1.596.947.551 0 1.059-.314 1.533-.947.472-.627.884-1.314 1.239-2.064.354-.744.629-1.455.826-2.123.196-.666.297-1.041.297-1.123.234-.863.51-1.828.824-2.891.313-1.063.592-2.025.826-2.893.237-.629.513-1.416.829-2.361.311-.946.589-1.85.824-2.716a242.12 242.12 0 0 0 1.893-5.666 172.94 172.94 0 0 0 1.888-6.378c.391-1.493.783-2.654 1.179-3.483.394-.825.865-1.433 1.416-1.829.552-.393 1.222-.628 2.008-.706a29.22 29.22 0 0 1 2.831-.119h1.479c.59 0 1.16.077 1.711.235a3.577 3.577 0 0 1 1.418.768c.389.355.587.926.587 1.713z" fill="#ff0" stroke="#504d49" stroke-width=".5"/><path d="M78.271 77.531c0 3.926-9.189 7.113-20.523 7.113-11.336 0-20.523-3.188-20.523-7.113 0-3.928 9.188-7.109 20.523-7.109 11.334 0 20.523 3.182 20.523 7.109z" fill="#7c9fbb"/><ellipse cx="62.657" cy="78.139" rx="9.595" ry="2.639" fill="#63839b"/><path d="M62.656 16.214c0 .048-.053.154-.15.313a.903.903 0 0 1-.459.354c-.545.246-1.17.382-1.885.407-.715.025-1.445.036-2.19.036-.547 0-1.121-.007-1.732-.018a8.751 8.751 0 0 1-1.732-.203 1.903 1.903 0 0 1-.865-.425c-.238-.212-.355-.366-.355-.464V1.072c0-.05.049-.148.152-.293.102-.15.254-.276.457-.372.543-.248 1.189-.375 1.934-.388C56.578.004 57.293 0 57.973 0c.473 0 1.033.004 1.68.019.645.013 1.273.079 1.883.203.342.072.613.208.816.407.207.198.305.345.305.443v15.142zM62.656 36.682c0 .051-.053.157-.15.316a.89.89 0 0 1-.459.35c-.545.249-1.17.385-1.885.41-.715.022-1.445.035-2.19.035-.547 0-1.121-.005-1.732-.017a8.679 8.679 0 0 1-1.732-.202 1.869 1.869 0 0 1-.865-.428c-.238-.21-.355-.364-.355-.464v-15.14c0-.049.049-.147.152-.295a1.16 1.16 0 0 1 .457-.371c.543-.246 1.189-.375 1.934-.389a102.378 102.378 0 0 1 3.822 0c.645.014 1.273.08 1.883.205.342.073.613.209.816.407.207.195.305.346.305.443v15.14z" fill="#504d49"/><path d="M62.656 57.152c0 .047-.053.154-.15.314a.905.905 0 0 1-.459.352c-.545.246-1.17.383-1.885.408a74.944 74.944 0 0 1-3.922.017 8.603 8.603 0 0 1-1.732-.205 1.89 1.89 0 0 1-.865-.422c-.238-.213-.355-.367-.355-.465V42.013c0-.05.049-.15.152-.296.102-.15.254-.273.457-.373.543-.247 1.189-.376 1.934-.39.748-.012 1.463-.018 2.142-.018.473 0 1.033.006 1.68.018.645.014 1.273.082 1.883.205.342.072.613.208.816.407.207.198.305.345.305.446v15.14z" fill="#ff0" stroke="#504d49" stroke-width=".5"/><path d="M62.656 77.389c0 .051-.053.156-.15.314a.897.897 0 0 1-.459.357c-.545.244-1.17.379-1.885.404a67.96 67.96 0 0 1-3.922.019 8.751 8.751 0 0 1-1.732-.203 1.878 1.878 0 0 1-.865-.428c-.238-.211-.355-.363-.355-.465V62.252c0-.049.049-.148.152-.297.102-.15.254-.273.457-.371.543-.246 1.189-.375 1.934-.389.748-.012 1.463-.018 2.142-.018.473 0 1.033.006 1.68.018.645.014 1.273.08 1.883.205.342.072.613.209.816.404.207.199.305.348.305.447v15.138z" fill="#504d49"/></g></svg>
|
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 78.272 84.645"><g id="indice-orange"><path d="M47.594 24.86c0 .233-.197.944-.59 2.123a480.704 480.704 0 0 1-2.656 7.733c-.432 1.22-.69 2.027-.77 2.421a88.378 88.378 0 0 1-1.414 4.134 133.507 133.507 0 0 0-1.533 4.367 82.222 82.222 0 0 1-1.42 4.31 747.465 747.465 0 0 0-1.533 4.307c-.317.869-.65 1.828-1.004 2.891a51.805 51.805 0 0 1-1.004 2.775 465.383 465.383 0 0 1-2.125 5.963 97.53 97.53 0 0 0-2.005 6.08c-.475 1.42-.944 2.5-1.418 3.246-.472.75-1.003 1.277-1.593 1.596-.592.313-1.281.49-2.065.531-.791.039-1.656.057-2.602.057-1.258 0-2.3-.039-3.124-.117-.829-.08-1.536-.371-2.127-.885-.589-.512-1.141-1.279-1.653-2.303-.51-1.021-1.045-2.479-1.596-4.369a706.87 706.87 0 0 0-7.376-21.898A1642.262 1642.262 0 0 1 .37 25.92a1.306 1.306 0 0 1-.12-.589v-.471c0-.787.194-1.379.592-1.773a2.828 2.828 0 0 1 1.416-.77 8.266 8.266 0 0 1 1.713-.175h3.718c.707 0 1.377.139 2.008.414.627.274 1.198.747 1.71 1.415.513.668.923 1.636 1.239 2.892.158.554.415 1.379.769 2.479.354 1.104.647 2.087.884 2.952a113.068 113.068 0 0 1 1.773 5.611 413.78 413.78 0 0 0 1.888 6.312c.314.871.63 1.873.946 3.014a45.059 45.059 0 0 0 1.062 3.365c.077.234.216.725.412 1.476.196.746.472 1.514.826 2.301.355.785.75 1.494 1.182 2.121.431.633.965.947 1.596.947.551 0 1.059-.314 1.533-.947.472-.627.884-1.314 1.239-2.064.354-.744.63-1.455.826-2.123.197-.666.297-1.041.297-1.123.235-.863.51-1.828.824-2.891.314-1.063.592-2.025.827-2.893.237-.629.513-1.416.829-2.361.312-.946.589-1.85.824-2.716.632-1.811 1.26-3.7 1.893-5.666a172.94 172.94 0 0 0 1.888-6.378c.39-1.493.783-2.654 1.178-3.483.393-.825.865-1.433 1.416-1.829.551-.393 1.222-.628 2.008-.707a29.256 29.256 0 0 1 2.832-.119h1.479c.59 0 1.16.077 1.711.235a3.574 3.574 0 0 1 1.418.769c.391.357.588.928.588 1.715z" fill="#fa0" stroke="#504d49" stroke-width=".5"/><path d="M78.272 77.531c0 3.926-9.189 7.113-20.523 7.113-11.336 0-20.524-3.188-20.524-7.113 0-3.928 9.188-7.109 20.524-7.109 11.333 0 20.523 3.182 20.523 7.109z" fill="#7c9fbb"/><ellipse cx="62.658" cy="78.139" rx="9.595" ry="2.639" fill="#63839b"/><path d="M62.657 16.214c0 .048-.053.154-.15.313a.903.903 0 0 1-.459.354c-.545.246-1.17.382-1.885.407-.715.025-1.445.036-2.189.036a96.9 96.9 0 0 1-1.733-.018 8.76 8.76 0 0 1-1.732-.203 1.903 1.903 0 0 1-.865-.425c-.238-.212-.355-.366-.355-.464V1.072c0-.05.049-.148.152-.293.102-.15.254-.276.457-.372.543-.248 1.189-.375 1.934-.388C56.579.004 57.293 0 57.973 0c.473 0 1.033.004 1.68.019.645.013 1.274.079 1.883.203.342.072.613.208.816.407.207.198.305.345.305.443v15.142z" fill="#504d49"/><path d="M62.657 36.682c0 .051-.053.157-.15.316a.89.89 0 0 1-.459.35c-.545.249-1.17.385-1.885.41-.715.023-1.445.035-2.189.035-.547 0-1.121-.005-1.733-.017a8.687 8.687 0 0 1-1.732-.202 1.869 1.869 0 0 1-.865-.428c-.238-.21-.355-.364-.355-.464v-15.14c0-.049.049-.147.152-.295a1.15 1.15 0 0 1 .457-.371c.543-.246 1.189-.375 1.934-.389a102.378 102.378 0 0 1 3.823 0c.645.014 1.274.08 1.883.205.342.073.613.209.816.407.207.195.305.346.305.443v15.14z" fill="#fa0" stroke="#504d49" stroke-width=".5"/><path d="M62.657 57.152c0 .047-.053.154-.15.314a.905.905 0 0 1-.459.352c-.545.246-1.17.383-1.885.408a75.085 75.085 0 0 1-3.922.017 8.611 8.611 0 0 1-1.732-.205 1.89 1.89 0 0 1-.865-.422c-.238-.213-.355-.367-.355-.465V42.013c0-.05.049-.15.152-.296.102-.15.254-.273.457-.373.543-.247 1.189-.376 1.934-.39.748-.012 1.463-.018 2.143-.018.473 0 1.033.006 1.68.018.645.014 1.274.082 1.883.205.342.072.613.208.816.407.207.198.305.345.305.446v15.14zM62.657 77.389c0 .051-.053.156-.15.314a.897.897 0 0 1-.459.357c-.545.244-1.17.379-1.885.404a65.179 65.179 0 0 1-3.922.019 8.76 8.76 0 0 1-1.732-.203 1.878 1.878 0 0 1-.865-.428c-.238-.211-.355-.363-.355-.465V62.252c0-.049.049-.148.152-.297.102-.15.254-.273.457-.371.543-.246 1.189-.375 1.934-.389.748-.012 1.463-.018 2.143-.018.473 0 1.033.006 1.68.018.645.014 1.274.08 1.883.205.342.072.613.209.816.404.207.199.305.348.305.447v15.138z" fill="#504d49"/></g></svg>
|
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 78.272 84.895"><g id="indice-rouge"><path d="M47.594 25.11c0 .233-.196.944-.589 2.123a576.842 576.842 0 0 1-1.299 3.838 365.141 365.141 0 0 1-1.358 3.895c-.432 1.22-.689 2.027-.77 2.421a90.678 90.678 0 0 1-1.413 4.134 131.995 131.995 0 0 0-1.533 4.367 82.954 82.954 0 0 1-1.421 4.312 747.465 747.465 0 0 0-1.533 4.307c-.316.869-.649 1.828-1.004 2.891a52.449 52.449 0 0 1-1.004 2.775 476.542 476.542 0 0 1-2.125 5.963 97.53 97.53 0 0 0-2.005 6.08c-.475 1.419-.944 2.499-1.418 3.246-.472.75-1.003 1.277-1.593 1.596-.592.313-1.281.489-2.065.53-.79.04-1.656.058-2.602.058-1.258 0-2.3-.039-3.124-.117-.829-.08-1.536-.372-2.127-.885-.589-.513-1.141-1.279-1.653-2.303-.51-1.022-1.044-2.479-1.596-4.369a706.134 706.134 0 0 0-7.377-21.9A1671.14 1671.14 0 0 1 .371 26.171a1.303 1.303 0 0 1-.12-.589v-.471c0-.787.194-1.379.592-1.773a2.828 2.828 0 0 1 1.416-.77 8.266 8.266 0 0 1 1.713-.175H7.69a4.96 4.96 0 0 1 2.008.415c.627.274 1.198.747 1.71 1.415.513.668.923 1.636 1.239 2.892.158.554.415 1.379.769 2.479.354 1.104.647 2.087.884 2.952a113.068 113.068 0 0 1 1.773 5.611 413.96 413.96 0 0 0 1.888 6.313c.314.87.63 1.873.946 3.014a44.882 44.882 0 0 0 1.061 3.364c.077.235.216.726.412 1.478.196.746.472 1.513.826 2.3.355.786.75 1.495 1.182 2.122.431.633.965.947 1.596.947.551 0 1.059-.314 1.533-.947.472-.627.884-1.314 1.239-2.064.354-.745.63-1.455.826-2.124.197-.666.297-1.041.297-1.122.235-.864.51-1.828.824-2.891.314-1.062.592-2.025.827-2.893.237-.63.513-1.416.829-2.362.312-.946.589-1.85.824-2.716.632-1.811 1.26-3.7 1.893-5.666a172.94 172.94 0 0 0 1.888-6.378c.39-1.493.783-2.654 1.178-3.483.393-.825.865-1.433 1.416-1.829.551-.393 1.222-.628 2.008-.707a29.242 29.242 0 0 1 2.832-.119h1.479c.589 0 1.159.077 1.71.235a3.59 3.59 0 0 1 1.419.769c.391.354.588.925.588 1.712z" fill="red" stroke="#504d49" stroke-width=".5"/><path d="M78.272 77.782c0 3.926-9.19 7.113-20.524 7.113-11.335 0-20.523-3.188-20.523-7.113 0-3.928 9.188-7.109 20.523-7.109 11.334-.001 20.524 3.181 20.524 7.109z" fill="#7c9fbb"/><ellipse cx="62.658" cy="78.389" rx="9.594" ry="2.639" fill="#63839b"/><path d="M62.656 16.464c0 .048-.053.154-.15.313a.896.896 0 0 1-.458.354c-.546.246-1.171.382-1.886.407-.714.025-1.444.036-2.19.036-.547 0-1.121-.007-1.732-.018a8.76 8.76 0 0 1-1.732-.203 1.9 1.9 0 0 1-.864-.425c-.239-.212-.356-.366-.356-.464V1.322c0-.05.05-.148.152-.293.102-.15.254-.276.458-.372.542-.248 1.188-.375 1.933-.388.748-.015 1.463-.019 2.143-.019.473 0 1.033.004 1.68.019.644.013 1.274.079 1.883.203.343.072.613.208.816.407.207.198.305.345.305.443v15.142z" fill="red" stroke="#504d49" stroke-width=".5"/><path d="M62.656 36.932c0 .051-.053.157-.15.316a.884.884 0 0 1-.458.35c-.546.249-1.171.385-1.886.41a71.04 71.04 0 0 1-2.19.035c-.547 0-1.121-.005-1.732-.017a8.687 8.687 0 0 1-1.732-.202 1.865 1.865 0 0 1-.864-.428c-.239-.21-.356-.364-.356-.464v-15.14c0-.049.05-.147.152-.295s.254-.271.458-.371c.542-.246 1.188-.375 1.933-.389a102.378 102.378 0 0 1 3.823 0c.644.014 1.274.08 1.883.205.343.073.613.209.816.407.207.195.305.346.305.443v15.14zM62.656 57.403c0 .047-.053.154-.15.313a.894.894 0 0 1-.458.353c-.546.246-1.171.383-1.886.408a71.04 71.04 0 0 1-3.922.017 8.611 8.611 0 0 1-1.732-.205 1.886 1.886 0 0 1-.864-.422c-.239-.213-.356-.367-.356-.465v-15.14c0-.05.05-.15.152-.296.102-.15.254-.273.458-.373.542-.247 1.188-.376 1.933-.39.748-.012 1.463-.018 2.143-.018.473 0 1.033.006 1.68.018.644.014 1.274.082 1.883.205.343.072.613.208.816.407.207.198.305.345.305.446v15.142zM62.656 77.639c0 .051-.053.156-.15.314a.9.9 0 0 1-.458.357c-.546.244-1.171.378-1.886.404a67.857 67.857 0 0 1-3.922.019 8.76 8.76 0 0 1-1.732-.203 1.884 1.884 0 0 1-.864-.428c-.239-.211-.356-.363-.356-.465V62.502c0-.05.05-.148.152-.297.102-.15.254-.273.458-.371.542-.246 1.188-.375 1.933-.389a93.232 93.232 0 0 1 3.823 0c.644.014 1.274.08 1.883.204.343.072.613.209.816.405.207.199.305.348.305.447v15.138z" fill="#504d49"/></g></svg>
|
After Width: | Height: | Size: 3.8 KiB |
@ -0,0 +1,50 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIII6DCCBtCgAwIBAgIRAKyivjc1wLX1ahBKQr2wLpwwDQYJKoZIhvcNAQELBQAw
|
||||
fTELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURISU1ZT1RJUzEcMBoGA1UECwwTMDAw
|
||||
MiA0ODE0NjMwODEwMDAzNjEdMBsGA1UEYQwUTlRSRlItNDgxNDYzMDgxMDAwMzYx
|
||||
HTAbBgNVBAMMFENlcnRpZ25hIFNlcnZpY2VzIENBMB4XDTIwMDkxMDA4NDM0NloX
|
||||
DTIxMDkxMDA4NDM0NlowgZgxCzAJBgNVBAYTAkZSMRkwFwYDVQQHDBBQQVJJUyBM
|
||||
QSBERUZFTlNFMSAwHgYDVQQKDBdTRyBNSU4gVFJBTlMgRUNPTCBTT0xJRDEcMBoG
|
||||
A1UECwwTMDAwMiAxMzAwMTk1NDAwMDAyNTEaMBgGA1UEAwwRdmlnaWNydWVzLmdv
|
||||
dXYuZnIxEjAQBgNVBAUTCVMxNzQ1ODAxNDCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||
ADCCAQoCggEBAOxiWSS7UVERcuH6PI4Itkm3hNos8wiwmbI1mtHht4a94h9gxzQ1
|
||||
U0t/wxYkOgzdQ3VCSNgX27YOEsfJKlqREx3AaSdztPW27mXCgl3+IOF6bm0UooIn
|
||||
gcl0inpGYJCI4Mb+2xEpmeJt2eEojQgiYQZVJuf2yOoNpCdNJlS/ym3LM1AQVxBm
|
||||
/Jl24KWbhr7cjPye0773jqckwf3JSFbqVtxinctVnnS+qdwn/hQP3nNBkXXKOnJM
|
||||
71vD7S4MwIMy3oQHK8oYmTwQpliju8rOIVKu099hiQAcegh5b33gG2RagHaTd6vb
|
||||
sunW5GBWS4IfhQurQT5pjKnVT4zpF/h4b+kCAwEAAaOCBEUwggRBMAkGA1UdEwQC
|
||||
MAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMGUGA1UdHwRe
|
||||
MFwwK6ApoCeGJWh0dHA6Ly9jcmwuY2VydGlnbmEuZnIvc2VydmljZXNjYS5jcmww
|
||||
LaAroCmGJ2h0dHA6Ly9jcmwuZGhpbXlvdGlzLmNvbS9zZXJ2aWNlc2NhLmNybDCB
|
||||
5AYIKwYBBQUHAQEEgdcwgdQwNgYIKwYBBQUHMAKGKmh0dHA6Ly9hdXRvcml0ZS5j
|
||||
ZXJ0aWduYS5mci9zZXJ2aWNlc2NhLmRlcjA4BggrBgEFBQcwAoYsaHR0cDovL2F1
|
||||
dG9yaXRlLmRoaW15b3Rpcy5jb20vc2VydmljZXNjYS5kZXIwLgYIKwYBBQUHMAGG
|
||||
Imh0dHA6Ly9zZXJ2aWNlc2NhLm9jc3AuY2VydGlnbmEuZnIwMAYIKwYBBQUHMAGG
|
||||
JGh0dHA6Ly9zZXJ2aWNlc2NhLm9jc3AuZGhpbXlvdGlzLmNvbTAdBgNVHQ4EFgQU
|
||||
nWuFMLSW73ZLFxHfrbThfMgS5n0wHwYDVR0jBBgwFoAUrOyGj0s3HLh/FxsZ0K7o
|
||||
TuM0XBIwMwYDVR0RBCwwKoIRdmlnaWNydWVzLmdvdXYuZnKCFXd3dy52aWdpY3J1
|
||||
ZXMuZ291di5mcjBUBgNVHSAETTBLMAgGBmeBDAECAjA/BgsqgXoBgTECBQEBATAw
|
||||
MC4GCCsGAQUFBwIBFiJodHRwczovL3d3dy5jZXJ0aWduYS5mci9hdXRvcml0ZXMv
|
||||
MIIB9AYKKwYBBAHWeQIEAgSCAeQEggHgAd4AdQBElGUusO7Or8RAB9io/ijA2uaC
|
||||
vtjLMbU/0zOWtbaBqAAAAXR3L2RPAAAEAwBGMEQCIDtx/No4sejdX5EvrDXcs4MD
|
||||
nqYZQymUgF6BEsDI8QBtAiAYOV8IqtH4+C2xMlaWWQSsu0+porprbou01OF7OaPM
|
||||
QQB2AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABdHcvZRMAAAQD
|
||||
AEcwRQIgSxFpdehqbsWZavfyc9/qfRp3mZDwxgKWtYWvKWD3jCYCIQDzBkPoaS0R
|
||||
5NwUKNy5M74Mki6NOJOX3oKpw/lRjKd5ywB1AFzcQ5L+5qtFRLFemtRW5hA3+9X6
|
||||
R9yhc5SyXub2xw7KAAABdHcvZ4MAAAQDAEYwRAIgfKfHw+kC5FHov2fo3Igs0Umu
|
||||
FSmG65zKYv6C5idM+NoCIEddMJWt2e+K6ejFxILKGSzx2pyj5f8J0N0jBwjquQt0
|
||||
AHYA9lyUL9F3MCIUVBgIMJRWjuNNExkzv98MLyALzE7xZOMAAAF0dy9oWgAABAMA
|
||||
RzBFAiEAimauUItb/FhM/KFNrF6pKpq3msq69vf8szYg6HDKq4cCIApAx7DUecse
|
||||
TeUBpfeJa6618/Yx4HWlbEDjXyToS0LEMA0GCSqGSIb3DQEBCwUAA4ICAQAXkoT/
|
||||
QGyvyNx9MlSuVE+CqRYJd2h0UsQjU1tjNWIwT/grodh3M5eYMbPv+mG1Kg8a95lG
|
||||
PazIJCxhXde77NQF5yXDEY6D7SFqs5s+Ah/oCxmkRNY+ctIrV++lyl24cVrLuMgc
|
||||
QHxtIDveFEHH7KsqrhcHkzrTG2tWcxD3j9p+mZu1t4xuOT46WfONMOBv9I0O+jVV
|
||||
2LpR5Qblf6Rvr9a0OopYCeTYT2q91A2XR7hUDxFXBVt+AB3eIOqbRUj0J+1xMjhJ
|
||||
XhqiaJpGQDf0CvSVE+ej5nafV/+eCS11u9U20B9vBl8JTKGq7lr8jhL3IPOb/EQG
|
||||
whh6/aYGT6bRh0L68FXRCclVDjFI7sTP0ZKcjGi1oCdCHP7d00xWg8z5fY4lEdkR
|
||||
6TfpkqBoYF5pnsikoDxX/U52w2+KvU84aOhSf+LkGigDUu+4+FJw4q4hdfevgdVW
|
||||
gM7vS4LzLTwnaXh+qGipuiWUUz6ublhM6iLn8ff2T82I6ggTHSvRswZfZciRrp4r
|
||||
m63QWF1dPQdvRBIeuAp772gKnUATGNKDF5XhE8NFvvIiLDFjHsiTGSx8UUzrPRdd
|
||||
0LXhFz8Dx4ciG4Y6sKnJbp4Lsu/is12n6eAzhId8YZSE0FGLSShKB27cWJ+VyIad
|
||||
qkouOhMnN18+YFQsMZM6qISdOTz+jQlU+DOMBg==
|
||||
-----END CERTIFICATE-----
|
Loading…
Reference in New Issue
Block a user