[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
|
## 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
|
## Binding Configuration
|
||||||
|
|
||||||
|
@ -41,13 +44,31 @@ The thing has a few configuration parameters:
|
||||||
|
|
||||||
## Channels
|
## 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:
|
The VigiCrues information that retrieved are made available with these channels:
|
||||||
|
|
||||||
| Channel ID | Item Type | Description |
|
| Channel ID | Item Type | Description |
|
||||||
|------------------|---------------------------|-------------------------------|
|
|------------------|---------------------------|------------------------------------------------------------|
|
||||||
| observation-time | DateTime | Date and time of measurement |
|
| observation-time | DateTime | Date and time of measurement |
|
||||||
| flow | Number:VolumetricFlowRate | Volume of water per time unit |
|
| flow | Number:VolumetricFlowRate | Volume of water per time unit |
|
||||||
| height | Number:Length | Water height of the river |
|
| 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
|
## Full Example
|
||||||
|
|
|
@ -15,13 +15,15 @@ package org.openhab.binding.vigicrues.internal;
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
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.
|
* thing configuration.
|
||||||
*
|
*
|
||||||
* @author Gaël L'hopital - Initial contribution
|
* @author Gaël L'hopital - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class VigiCruesConfiguration {
|
public class StationConfiguration {
|
||||||
|
public static String ID = "id";
|
||||||
|
|
||||||
public String id = "";
|
public String id = "";
|
||||||
public int refresh = 30;
|
public int refresh = 30;
|
||||||
}
|
}
|
|
@ -28,17 +28,27 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||||
public class VigiCruesBindingConstants {
|
public class VigiCruesBindingConstants {
|
||||||
|
|
||||||
public static final String BINDING_ID = "vigicrues";
|
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
|
// 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
|
// List of all Channel id's
|
||||||
public static final String OBSERVATION_TIME = "observation-time";
|
public static final String OBSERVATION_TIME = "observation-time";
|
||||||
public static final String HEIGHT = "height";
|
public static final String HEIGHT = "height";
|
||||||
public static final String FLOW = "flow";
|
public static final String FLOW = "flow";
|
||||||
|
public static final String ALERT = "alert";
|
||||||
public static final String COMMENT = "comment";
|
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;
|
package org.openhab.binding.vigicrues.internal;
|
||||||
|
|
||||||
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.*;
|
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.SUPPORTED_THING_TYPES_UIDS;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
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.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.Thing;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
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.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
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
|
* The {@link VigiCruesHandlerFactory} is responsible for creating things and thing
|
||||||
* handlers.
|
* handlers.
|
||||||
|
@ -42,17 +37,13 @@ import com.google.gson.JsonDeserializer;
|
||||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.vigicrues")
|
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.vigicrues")
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class VigiCruesHandlerFactory extends BaseThingHandlerFactory {
|
public class VigiCruesHandlerFactory extends BaseThingHandlerFactory {
|
||||||
private final Gson gson;
|
private final LocationProvider locationProvider;
|
||||||
// Needed for converting UTC time to local time
|
private final ApiHandler apiHandler;
|
||||||
private final TimeZoneProvider timeZoneProvider;
|
|
||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public VigiCruesHandlerFactory(@Reference TimeZoneProvider timeZoneProvider) {
|
public VigiCruesHandlerFactory(@Reference ApiHandler apiHandler, @Reference LocationProvider locationProvider) {
|
||||||
this.timeZoneProvider = timeZoneProvider;
|
this.locationProvider = locationProvider;
|
||||||
this.gson = new GsonBuilder()
|
this.apiHandler = apiHandler;
|
||||||
.registerTypeAdapter(ZonedDateTime.class, (JsonDeserializer<ZonedDateTime>) (json, type,
|
|
||||||
jsonDeserializationContext) -> ZonedDateTime.parse(json.getAsJsonPrimitive().getAsString()))
|
|
||||||
.create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,11 +54,6 @@ public class VigiCruesHandlerFactory extends BaseThingHandlerFactory {
|
||||||
@Override
|
@Override
|
||||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
|
return supportsThingType(thingTypeUID) ? new VigiCruesHandler(thing, locationProvider, apiHandler) : null;
|
||||||
if (thingTypeUID.equals(THING_TYPE_VIGI_CRUES)) {
|
|
||||||
return new VigiCruesHandler(thing, timeZoneProvider, gson);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 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
|
* 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 java.util.Optional;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
@ -30,7 +32,7 @@ public class OpenDatasoftResponse {
|
||||||
@SerializedName("nhits")
|
@SerializedName("nhits")
|
||||||
private int nHits;
|
private int nHits;
|
||||||
private @Nullable Parameters parameters;
|
private @Nullable Parameters parameters;
|
||||||
private Record[] records = {};
|
private List<Record> records = new ArrayList<>();
|
||||||
|
|
||||||
public int getNHits() {
|
public int getNHits() {
|
||||||
return nHits;
|
return nHits;
|
||||||
|
@ -44,7 +46,7 @@ public class OpenDatasoftResponse {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Record[] getRecords() {
|
public Optional<VigiCruesFields> getFirstRecord() {
|
||||||
return records;
|
return records.stream().findFirst().flatMap(Record::getFields);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* 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.time.ZoneId;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* 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;
|
import java.util.Optional;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* 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;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* 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.time.ZonedDateTime;
|
||||||
import java.util.Optional;
|
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;
|
package org.openhab.binding.vigicrues.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.vigicrues.internal.VigiCruesBindingConstants.*;
|
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.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.io.InputStream;
|
||||||
import java.time.ZonedDateTime;
|
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.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.measure.Unit;
|
import javax.measure.Unit;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.vigicrues.internal.VigiCruesConfiguration;
|
import org.openhab.binding.vigicrues.internal.StationConfiguration;
|
||||||
import org.openhab.binding.vigicrues.internal.json.OpenDatasoftResponse;
|
import org.openhab.binding.vigicrues.internal.api.ApiHandler;
|
||||||
import org.openhab.binding.vigicrues.internal.json.Record;
|
import org.openhab.binding.vigicrues.internal.api.VigiCruesException;
|
||||||
import org.openhab.core.i18n.TimeZoneProvider;
|
import org.openhab.binding.vigicrues.internal.dto.hubeau.HubEauResponse;
|
||||||
import org.openhab.core.io.net.http.HttpUtil;
|
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.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.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.ChannelUID;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.ThingStatus;
|
import org.openhab.core.thing.ThingStatus;
|
||||||
import org.openhab.core.thing.ThingStatusDetail;
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
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.Command;
|
||||||
import org.openhab.core.types.RefreshType;
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.openhab.core.types.UnDefType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link VigiCruesHandler} is responsible for querying the API and
|
* The {@link VigiCruesHandler} is responsible for querying the API and
|
||||||
* updating channels
|
* updating channels
|
||||||
|
@ -54,35 +70,124 @@ import com.google.gson.Gson;
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class VigiCruesHandler extends BaseThingHandler {
|
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 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 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);
|
super(thing);
|
||||||
this.timeZoneProvider = timeZoneProvider;
|
this.apiHandler = apiHandler;
|
||||||
this.gson = gson;
|
this.locationProvider = locationProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
logger.debug("Initializing VigiCrues handler.");
|
logger.debug("Initializing VigiCrues handler.");
|
||||||
|
|
||||||
VigiCruesConfiguration config = getConfigAs(VigiCruesConfiguration.class);
|
StationConfiguration config = getConfigAs(StationConfiguration.class);
|
||||||
logger.debug("config station = {}", config.id);
|
|
||||||
logger.debug("config refresh = {} min", config.refresh);
|
logger.debug("config refresh = {} min", config.refresh);
|
||||||
|
|
||||||
updateStatus(ThingStatus.UNKNOWN);
|
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);
|
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
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
logger.debug("Disposing the VigiCrues handler.");
|
logger.debug("Disposing the VigiCrues handler.");
|
||||||
|
@ -102,26 +207,43 @@ public class VigiCruesHandler extends BaseThingHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAndPublish() {
|
private void updateAndPublish() {
|
||||||
|
StationConfiguration config = getConfigAs(StationConfiguration.class);
|
||||||
try {
|
try {
|
||||||
if (queryUrl != null) {
|
OpenDatasoftResponse measures = apiHandler.getMeasures(config.id);
|
||||||
String response = HttpUtil.executeUrl("GET", queryUrl, TIMEOUT_MS);
|
measures.getFirstRecord().ifPresent(field -> {
|
||||||
updateStatus(ThingStatus.ONLINE);
|
field.getHeight().ifPresent(height -> {
|
||||||
OpenDatasoftResponse apiResponse = gson.fromJson(response, OpenDatasoftResponse.class);
|
updateQuantity(HEIGHT, height, SIUnits.METRE);
|
||||||
Arrays.stream(apiResponse.getRecords()).findFirst().flatMap(Record::getFields).ifPresent(field -> {
|
updateRelativeMeasure(RELATIVE_HEIGHT, referenceHeights, height);
|
||||||
field.getHeight().ifPresent(height -> updateQuantity(HEIGHT, height, METRE));
|
});
|
||||||
field.getFlow().ifPresent(flow -> updateQuantity(FLOW, flow, CUBICMETRE_PER_SECOND));
|
field.getFlow().ifPresent(flow -> {
|
||||||
|
updateQuantity(FLOW, flow, SmartHomeUnits.CUBICMETRE_PER_SECOND);
|
||||||
|
updateRelativeMeasure(RELATIVE_FLOW, referenceFlows, flow);
|
||||||
|
});
|
||||||
field.getTimestamp().ifPresent(date -> updateDate(OBSERVATION_TIME, date));
|
field.getTimestamp().ifPresent(date -> updateDate(OBSERVATION_TIME, date));
|
||||||
});
|
});
|
||||||
} else {
|
String currentPortion = this.portion;
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DISABLED,
|
if (currentPortion != null) {
|
||||||
"queryUrl should never be null, but it is !");
|
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.ONLINE);
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
} catch (VigiCruesException e) {
|
||||||
String.format("Querying '%s' raised : %s", queryUrl, e.getMessage()));
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||||
} catch (IOException e) {
|
}
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
}
|
||||||
String.format("Error opening connection to VigiCrues webservice : {}", 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) {
|
public void updateDate(String channelId, ZonedDateTime zonedDateTime) {
|
||||||
if (isLinked(channelId)) {
|
if (isLinked(channelId)) {
|
||||||
ZonedDateTime localDateTime = zonedDateTime.withZoneSameInstant(timeZoneProvider.getTimeZone());
|
updateState(channelId, new DateTimeType(zonedDateTime));
|
||||||
updateState(channelId, new DateTimeType(localDateTime));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>
|
<channels>
|
||||||
<channel id="height" typeId="height"/>
|
<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="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"/>
|
<channel id="observation-time" typeId="observation-time"/>
|
||||||
</channels>
|
</channels>
|
||||||
|
|
||||||
|
<representation-property>id</representation-property>
|
||||||
|
|
||||||
<config-description>
|
<config-description>
|
||||||
<parameter name="id" type="text" required="true">
|
<parameter name="id" type="text" required="true">
|
||||||
<label>Identifiant</label>
|
<label>Identifiant</label>
|
||||||
|
@ -32,6 +50,7 @@
|
||||||
<channel-type id="flow">
|
<channel-type id="flow">
|
||||||
<item-type>Number:VolumetricFlowRate</item-type>
|
<item-type>Number:VolumetricFlowRate</item-type>
|
||||||
<label>Current Flow</label>
|
<label>Current Flow</label>
|
||||||
|
<category>flow</category>
|
||||||
<state readOnly="true" pattern="%.2f %unit%"/>
|
<state readOnly="true" pattern="%.2f %unit%"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
|
@ -39,6 +58,7 @@
|
||||||
<item-type>DateTime</item-type>
|
<item-type>DateTime</item-type>
|
||||||
<label>Observation Time</label>
|
<label>Observation Time</label>
|
||||||
<description>Observation date and time</description>
|
<description>Observation date and time</description>
|
||||||
|
<category>time</category>
|
||||||
<state readOnly="true"/>
|
<state readOnly="true"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
|
@ -48,4 +68,36 @@
|
||||||
<description>Water level in the river</description>
|
<description>Water level in the river</description>
|
||||||
<state readOnly="true" pattern="%.2f %unit%"/>
|
<state readOnly="true" pattern="%.2f %unit%"/>
|
||||||
</channel-type>
|
</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>
|
</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