/bundles/org.openhab.binding.mecmeter/ @kaikreuzer
/bundles/org.openhab.binding.melcloud/ @lucacalcaterra @paulianttila @thewiep
/bundles/org.openhab.binding.mercedesme/ @weymann
-/bundles/org.openhab.binding.meteoalerte/ @clinique
/bundles/org.openhab.binding.meteoblue/ @9037568
+/bundles/org.openhab.binding.meteofrance/ @clinique
/bundles/org.openhab.binding.meteostick/ @cdjackson
/bundles/org.openhab.binding.mffan/ @mark-brooks-180
/bundles/org.openhab.binding.miele/ @kgoderis @jlaur
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
- <artifactId>org.openhab.binding.meteoalerte</artifactId>
+ <artifactId>org.openhab.binding.meteoblue</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
- <artifactId>org.openhab.binding.meteoblue</artifactId>
+ <artifactId>org.openhab.binding.meteofrance</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
+++ /dev/null
-This content is produced and maintained by the openHAB project.
-
-* Project home: https://www.openhab.org
-
-== Declared Project Licenses
-
-This program and the accompanying materials are made available under the terms
-of the Eclipse Public License 2.0 which is available at
-https://www.eclipse.org/legal/epl-2.0/.
-
-== Source Code
-
-https://github.com/openhab/openhab-addons
+++ /dev/null
-# Meteo Alerte Binding
-
-The Meteo Alerte binding gives alert level regarding major weather related risk factors.
-This binding provides its own icon set and provides appropriate static and dynamic SVG icons (see items examples below).
-
-## Supported Things
-
-There is exactly one supported thing type, which represents the weather alerts for a given department.
-It has the `department` id.
-Of course, you can add multiple things, e.g. for getting alerts for different locations.
-
-## Binding Configuration
-
-The binding has no configuration options, all configuration is done at Thing level.
-
-## Thing Configuration
-
-The thing has a few configuration parameters:
-
-| Parameter | Description |
-|---------------|----------------------------------------------------------------------------------------|
-| `department` | Name of the department. |
-| refresh | Refresh interval in minutes. Optional, the default value is 1440 minutes (once a day). |
-
-## Channels
-
-The Météo Alerte information that are retrieved is available as these channels:
-
-| Channel ID | Item Type | Description |
-|-----------------------|-----------|-----------------------------------------------|
-| observation-time | DateTime | Date and time of report validity start |
-| end-time | DateTime | Date and time of report validity end |
-| comment | String | General comments on alerts for the department |
-| vent | Number | Wind alert level (*) |
-| pluie-inondation | Number | Rain alert level (*) |
-| orage | Number | Storm alert level (*) |
-| inondation | Number | Flood alert level (*) |
-| neige | Number | Snow alert level (*) |
-| canicule | Number | Heat alert level (*) |
-| grand-froid | Number | Cold alert level (*) |
-| avalanches | Number | Avalanche alert level (*) |
-| vague-submersion | Number | Wave submersion alert level (*) |
-| pluie-inondation-icon | Image | Pictogram of the Rain alert level |
-| vent-icon | Image | Pictogram of the Wind alert level |
-| orage-icon | Image | Pictogram of Storm alert level |
-| inondation-icon | Image | Pictogram of Flood alert level |
-| neige-icon | Image | Pictogram of Snow alert level |
-| canicule-icon | Image | Pictogram of Heat alert level |
-| grand-froid-icon | Image | Pictogram of Cold alert level |
-| avalanches-icon | Image | Pictogram of Avalanche alert level |
-| vague-submersion-icon | Image | Pictogram of Wave Submersion alert level |
-
-(*) Each alert level is described by a color :
-
-| Code | Color | Description |
-|------|--------|-------------------------------------------|
-| 0 | Green | No particular vigilance |
-| 1 | Yellow | Be attentive to the weather situation |
-| 2 | Orange | Be "very vigilant" in the concerned areas |
-| 3 | Red | Absolute vigilance required |
-
-## Provided icon set
-
-This binding has its own IconProvider and makes available the following list of icons
-
-| Icon Name | Dynamic | Illustration |
-|---------------------------------|---------|--------------|
-| oh:meteoalerte:vent | Yes |  |
-| oh:meteoalerte:pluie-inondation | Yes |  |
-| oh:meteoalerte:orage | Yes |  |
-| oh:meteoalerte:inondation | Yes |  |
-| oh:meteoalerte:neige | Yes |  |
-| oh:meteoalerte:canicule | Yes |  |
-| oh:meteoalerte:grand-froid | Yes |  |
-| oh:meteoalerte:avalanches | Yes |  |
-| oh:meteoalerte:vague-submersion | Yes |  |
-| oh:meteoalerte:meteo_france | No |  |
-
-
-## Full Example
-
-meteoalert.things:
-
-```java
-Thing meteoalerte:department:yvelines @ "MyCity" [department="YVELINES", refresh=12]
-```
-
-meteoalert.items:
-
-```java
-Group gMeteoAlert "Alertes Météo" <oh:meteoalerte:meteo_france>
-String MA_Dept78 "Département 78 [%s]" <text> (gMeteoAlert) {channel="meteoalerte:department:yvelines:comment"}
-Number MA_etat_canicule "Canicule [%s]" <oh:meteoalerte:canicule> (gMeteoAlert) {channel="meteoalerte:department:yvelines:canicule"}
-Number MA_etat_grand_froid "Grand Froid [%s]" <oh:meteoalerte:grand-froid> (gMeteoAlert) {channel="meteoalerte:department:yvelines:grand-froid"}
-Number MA_etat_pluie_inondation "Pluie-Inondation [%s]" <oh:meteoalerte:pluie-inondation> (gMeteoAlert) {channel="meteoalerte:department:yvelines:pluie-inondation"}
-Number MA_etat_neige "Neige [%s]" <oh:meteoalerte:neige> (gMeteoAlert) {channel="meteoalerte:department:yvelines:neige"}
-Number MA_etat_vent "Vent [%s]" <oh:meteoalerte:vent> (gMeteoAlert) {channel="meteoalerte:department:yvelines:vent"}
-Number MA_etat_inondation "Inondation [%s]" <oh:meteoalerte:inondation> (gMeteoAlert) {channel="meteoalerte:department:yvelines:inondation"}
-Number MA_etat_orage "Orage [%s]" <oh:meteoalerte:orage> (gMeteoAlert) {channel="meteoalerte:department:yvelines:orage"}
-Number MA_etat_avalanche "Avalanches [%s]" <oh:meteoalerte:avalanches> (gMeteoAlert) {channel="meteoalerte:department:yvelines:avalanches"}
-
-Image MA_icon_canicule "Canicule" <oh:meteoalerte:canicule> (gMeteoAlert) {channel="meteoalerte:department:yvelines:canicule-icon"}
-Image MA_icon_grand_froid "Grand Froid" <oh:meteoalerte:grand-froid> (gMeteoAlert) {channel="meteoalerte:department:yvelines:grand-froid-icon"}
-Image MA_icon_pluie_inondation "Pluie-Inondation" <oh:meteoalerte:pluie-inondation> (gMeteoAlert) {channel="meteoalerte:department:yvelines:pluie-inondation-icon"}
-Image MA_icon_neige "Neige" <oh:meteoalerte:neige> (gMeteoAlert) {channel="meteoalerte:department:yvelines:neige-icon"}
-Image MA_icon_vent "Vent" <oh:meteoalerte:vent> (gMeteoAlert) {channel="meteoalerte:department:yvelines:vent-icon"}
-Image MA_icon_inondation "Inondation" <oh:meteoalerte:inondation> (gMeteoAlert) {channel="meteoalerte:department:yvelines:inondation-icon"}
-Image MA_icon_orage "Orage" <oh:meteoalerte:orage> (gMeteoAlert) {channel="meteoalerte:department:yvelines:orage-icon"}
-Image MA_icon_avalanche "Avalanche" <oh:meteoalerte:avalanches> (gMeteoAlert) {channel="meteoalerte:department:yvelines:avalanches-icon"}
-
-DateTime MA_ObservationTS "Timestamp [%1$tH:%1$tM]" <time> (gMeteoAlert) {channel="meteoalerte:department:yvelines:observation-time"}
-
-```
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.openhab.addons.bundles</groupId>
- <artifactId>org.openhab.addons.reactor.bundles</artifactId>
- <version>4.3.0-SNAPSHOT</version>
- </parent>
-
- <artifactId>org.openhab.binding.meteoalerte</artifactId>
-
- <name>openHAB Add-ons :: Bundles :: Meteo Alerte Binding</name>
-
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<features name="org.openhab.binding.meteoalerte-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
- <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
-
- <feature name="openhab-binding-meteoalerte" description="Meteo Alerte Binding" version="${project.version}">
- <feature>openhab-runtime-base</feature>
- <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.meteoalerte/${project.version}</bundle>
- </feature>
-</features>
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal;
-
-import static org.openhab.binding.meteoalerte.internal.MeteoAlerteBindingConstants.*;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.Locale;
-import java.util.Set;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.meteoalerte.internal.json.ResponseFieldDTO.AlertLevel;
-import org.openhab.core.i18n.TranslationProvider;
-import org.openhab.core.ui.icon.IconProvider;
-import org.openhab.core.ui.icon.IconSet;
-import org.openhab.core.ui.icon.IconSet.Format;
-import org.osgi.framework.BundleContext;
-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 MeteoAlertIconProvider} is the class providing binding related icons.
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@Component(service = { IconProvider.class, MeteoAlertIconProvider.class })
-@NonNullByDefault
-public class MeteoAlertIconProvider implements IconProvider {
- private static final String DEFAULT_LABEL = "Météo Alerte Icons";
- private static final String DEFAULT_DESCRIPTION = "Icons illustrating weather events provided by Météo Alerte";
- private static final Set<String> ICONS = Set.of(WAVE, AVALANCHE, HEAT, FREEZE, FLOOD, SNOW, STORM, RAIN, WIND,
- "meteo_france");
-
- private final Logger logger = LoggerFactory.getLogger(MeteoAlertIconProvider.class);
- private final BundleContext context;
- private final TranslationProvider i18nProvider;
-
- @Activate
- public MeteoAlertIconProvider(final BundleContext context, final @Reference TranslationProvider i18nProvider) {
- this.context = context;
- this.i18nProvider = i18nProvider;
- }
-
- @Override
- public Set<IconSet> getIconSets() {
- return getIconSets(null);
- }
-
- @Override
- public Set<IconSet> getIconSets(@Nullable Locale locale) {
- String label = getText("label", DEFAULT_LABEL, locale);
- String description = getText("decription", DEFAULT_DESCRIPTION, locale);
-
- return Set.of(new IconSet(BINDING_ID, label, description, Set.of(Format.SVG)));
- }
-
- private String getText(String entry, String defaultValue, @Nullable Locale locale) {
- String text = defaultValue;
- if (locale != null) {
- text = i18nProvider.getText(context.getBundle(), "iconset." + entry, defaultValue, locale);
- text = text == null ? defaultValue : text;
- }
- return text;
- }
-
- @Override
- public @Nullable Integer hasIcon(String category, String iconSetId, Format format) {
- return ICONS.contains(category) && iconSetId.equals(BINDING_ID) && format == Format.SVG ? 0 : null;
- }
-
- public @Nullable InputStream getIcon(String category, String state) {
- return getIcon(category, BINDING_ID, state, Format.SVG);
- }
-
- @Override
- public @Nullable InputStream getIcon(String category, String iconSetId, @Nullable String state, Format format) {
- String icon = getResource(category);
- if (icon.isEmpty()) {
- return null;
- }
-
- if (state != null) {
- try {
- Integer ordinal = Integer.valueOf(state);
- AlertLevel alertLevel = ordinal < AlertLevel.values().length ? AlertLevel.values()[ordinal]
- : AlertLevel.UNKNOWN;
- icon = icon.replaceAll(AlertLevel.UNKNOWN.color, alertLevel.color);
- } catch (NumberFormatException e) {
- logger.debug("{} is not a valid DecimalType", state);
- }
- }
-
- return new ByteArrayInputStream(icon.getBytes());
- }
-
- private String getResource(String iconName) {
- String result = "";
-
- URL iconResource = context.getBundle().getEntry("icon/%s.svg".formatted(iconName));
- try (InputStream stream = iconResource.openStream()) {
- result = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
- } catch (IOException e) {
- logger.warn("Unable to load ressource '{}' : {}", iconResource.getPath(), e.getMessage());
- }
- return result;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.thing.ThingTypeUID;
-
-/**
- * The {@link MeteoAlerteBindingConstants} class defines common constants, which are
- * used across the whole binding.
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@NonNullByDefault
-public class MeteoAlerteBindingConstants {
- public static final String BINDING_ID = "meteoalerte";
-
- // List of all Thing Type UIDs
- public static final ThingTypeUID THING_TYPE_METEO_ALERT = new ThingTypeUID(BINDING_ID, "department");
-
- // List of all Channel IDs
- public static final String WAVE = "vague-submersion";
- public static final String AVALANCHE = "avalanches";
- public static final String HEAT = "canicule";
- public static final String FREEZE = "grand-froid";
- public static final String FLOOD = "inondation";
- public static final String SNOW = "neige";
- public static final String STORM = "orage";
- public static final String RAIN = "pluie-inondation";
- public static final String WIND = "vent";
- public static final String OBSERVATION_TIME = "observation-time";
- public static final String END_TIME = "end-time";
- public static final String COMMENT = "comment";
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link MeteoAlerteConfiguration} is the class used to match the
- * thing configuration.
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@NonNullByDefault
-public class MeteoAlerteConfiguration {
- public String department = "";
- public int refresh = 1440;
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal;
-
-import static org.openhab.binding.meteoalerte.internal.MeteoAlerteBindingConstants.THING_TYPE_METEO_ALERT;
-
-import java.time.ZonedDateTime;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.meteoalerte.internal.handler.MeteoAlerteHandler;
-import org.openhab.core.i18n.TimeZoneProvider;
-import org.openhab.core.thing.Thing;
-import org.openhab.core.thing.ThingTypeUID;
-import org.openhab.core.thing.binding.BaseThingHandlerFactory;
-import org.openhab.core.thing.binding.ThingHandler;
-import org.openhab.core.thing.binding.ThingHandlerFactory;
-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 MeteoAlerteHandlerFactory} is responsible for creating things and thing handlers.
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@Component(service = ThingHandlerFactory.class)
-@NonNullByDefault
-public class MeteoAlerteHandlerFactory extends BaseThingHandlerFactory {
- private final Gson gson;
- private final MeteoAlertIconProvider iconProvider;
-
- @Activate
- public MeteoAlerteHandlerFactory(@Reference TimeZoneProvider timeZoneProvider,
- @Reference MeteoAlertIconProvider iconProvider) {
- this.iconProvider = iconProvider;
- this.gson = new GsonBuilder().registerTypeAdapter(ZonedDateTime.class,
- (JsonDeserializer<ZonedDateTime>) (json, type, jsonDeserializationContext) -> ZonedDateTime
- .parse(json.getAsJsonPrimitive().getAsString())
- .withZoneSameInstant(timeZoneProvider.getTimeZone()))
- .create();
- }
-
- @Override
- public boolean supportsThingType(ThingTypeUID thingTypeUID) {
- return THING_TYPE_METEO_ALERT.equals(thingTypeUID);
- }
-
- @Override
- protected @Nullable ThingHandler createHandler(Thing thing) {
- ThingTypeUID thingTypeUID = thing.getThingTypeUID();
-
- return supportsThingType(thingTypeUID) ? new MeteoAlerteHandler(thing, gson, iconProvider) : null;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal.handler;
-
-import static org.openhab.binding.meteoalerte.internal.MeteoAlerteBindingConstants.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.time.ZonedDateTime;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.meteoalerte.internal.MeteoAlertIconProvider;
-import org.openhab.binding.meteoalerte.internal.MeteoAlerteConfiguration;
-import org.openhab.binding.meteoalerte.internal.json.ApiResponse;
-import org.openhab.binding.meteoalerte.internal.json.ResponseFieldDTO.AlertLevel;
-import org.openhab.core.io.net.http.HttpUtil;
-import org.openhab.core.library.types.DateTimeType;
-import org.openhab.core.library.types.DecimalType;
-import org.openhab.core.library.types.RawType;
-import org.openhab.core.library.types.StringType;
-import org.openhab.core.thing.ChannelUID;
-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.types.Command;
-import org.openhab.core.types.RefreshType;
-import org.openhab.core.types.State;
-import org.openhab.core.types.UnDefType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.gson.Gson;
-
-/**
- * The {@link MeteoAlerteHandler} is responsible for updating channels
- * and querying the API
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@NonNullByDefault
-public class MeteoAlerteHandler extends BaseThingHandler {
- private static final int TIMEOUT_MS = 30000;
- private static final String URL = """
- https://public.opendatasoft.com/api/records/1.0/search/?dataset=risques-meteorologiques-copy&\
- facet=etat_vent&facet=etat_pluie_inondation&facet=etat_orage&facet=etat_inondation&facet=etat_neige&facet=etat_canicule&\
- facet=etat_grand_froid&facet=etat_avalanches&refine.nom_dept=%s\
- """;
-
- private final Logger logger = LoggerFactory.getLogger(MeteoAlerteHandler.class);
- private final MeteoAlertIconProvider iconProvider;
- private final Gson gson;
-
- private Optional<ScheduledFuture<?>> refreshJob = Optional.empty();
- private String queryUrl = "";
-
- public MeteoAlerteHandler(Thing thing, Gson gson, MeteoAlertIconProvider iconProvider) {
- super(thing);
- this.gson = gson;
- this.iconProvider = iconProvider;
- }
-
- @Override
- public void initialize() {
- logger.debug("Initializing Météo Alerte handler.");
-
- MeteoAlerteConfiguration config = getConfigAs(MeteoAlerteConfiguration.class);
- logger.debug("config department = {}", config.department);
- logger.debug("config refresh = {}", config.refresh);
-
- updateStatus(ThingStatus.UNKNOWN);
- queryUrl = URL.formatted(config.department);
- refreshJob = Optional
- .of(scheduler.scheduleWithFixedDelay(this::updateAndPublish, 0, config.refresh, TimeUnit.MINUTES));
- }
-
- @Override
- public void dispose() {
- logger.debug("Disposing the Météo Alerte handler.");
-
- refreshJob.ifPresent(job -> job.cancel(true));
- refreshJob = Optional.empty();
- }
-
- @Override
- public void handleCommand(ChannelUID channelUID, Command command) {
- if (command instanceof RefreshType) {
- updateAndPublish();
- }
- }
-
- private void updateAndPublish() {
- try {
- if (queryUrl.isEmpty()) {
- throw new MalformedURLException("queryUrl not initialized");
- }
- String response = HttpUtil.executeUrl("GET", queryUrl, TIMEOUT_MS);
- if (response == null) {
- throw new IOException("Empty response");
- }
- updateStatus(ThingStatus.ONLINE);
- updateChannels(Objects.requireNonNull(gson.fromJson(response, ApiResponse.class)));
- } catch (MalformedURLException e) {
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
- "Querying '%s' error : %s".formatted(queryUrl, e.getMessage()));
- } catch (IOException e) {
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
- }
- }
-
- /**
- * Update the channel from the last Meteo Alerte data retrieved
- *
- * @param channelId the id identifying the channel to be updated
- */
- private void updateChannels(ApiResponse apiResponse) {
- apiResponse.getRecords().findFirst().ifPresent(record -> record.getResponseFieldDTO().ifPresent(fields -> {
- updateAlert(WIND, fields.getVent());
- updateAlert(RAIN, fields.getPluieInondation());
- updateAlert(STORM, fields.getOrage());
- updateAlert(FLOOD, fields.getInondation());
- updateAlert(SNOW, fields.getNeige());
- updateAlert(HEAT, fields.getCanicule());
- updateAlert(FREEZE, fields.getGrandFroid());
- updateAlert(AVALANCHE, fields.getAvalanches());
- updateAlert(WAVE, fields.getVagueSubmersion());
- updateState(COMMENT, StringType.valueOf(fields.getVigilanceComment()));
- fields.getDateInsert().ifPresent(date -> updateDate(OBSERVATION_TIME, date));
- fields.getDatePrevue().ifPresent(date -> updateDate(END_TIME, date));
- }));
- }
-
- private void updateAlert(String channelId, AlertLevel value) {
- State state = value != AlertLevel.UNKNOWN ? new DecimalType(value.ordinal()) : UnDefType.NULL;
- if (isLinked(channelId)) {
- updateState(channelId, state);
- }
-
- String channelIcon = channelId + "-icon";
- if (isLinked(channelIcon)) {
- InputStream icon = iconProvider.getIcon(channelId, state.toString());
- if (icon != null) {
- try {
- State result = new RawType(icon.readAllBytes(), "image/svg+xml");
- updateState(channelIcon, result);
- } catch (IOException e) {
- logger.warn("Error getting icon for channel {} and value {} : {}", channelId, value,
- e.getMessage());
- }
- } else {
- logger.warn("Null icon returned for channel {} and state {}", channelIcon, state);
- }
- }
- }
-
- private void updateDate(String channelId, ZonedDateTime zonedDateTime) {
- if (isLinked(channelId)) {
- updateState(channelId, new DateTimeType(zonedDateTime));
- }
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal.json;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Stream;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * The {@link ApiResponse} is the Java class used to map the JSON
- * response to the webservice request.
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@NonNullByDefault
-public class ApiResponse {
- @SerializedName("nhits")
- private int nHits;
- private @Nullable Parameters parameters;
- private List<Record> records = new ArrayList<>();
-
- public int getNHits() {
- return nHits;
- }
-
- public Optional<Parameters> getParameters() {
- return Optional.ofNullable(parameters);
- }
-
- public Stream<Record> getRecords() {
- return records.stream();
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal.json;
-
-import java.util.Optional;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * The {@link Parameters} is the Java class used to map the JSON
- * response to the webservice request.
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@NonNullByDefault
-public class Parameters {
- private String dataset = "";
- @SerializedName("timezone")
- private String timeZone = "";
- private int rows;
- private String format = "";
- private @Nullable Refine refine;
-
- public String getDataset() {
- return dataset;
- }
-
- public String getTimezone() {
- return timeZone;
- }
-
- public int getRows() {
- return rows;
- }
-
- public String getFormat() {
- return format;
- }
-
- public Optional<Refine> getRefine() {
- return Optional.ofNullable(refine);
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal.json;
-
-import java.util.Optional;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * The {@link Record} is the Java class used to map the JSON
- * response to the webservice request.
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@NonNullByDefault
-public class Record {
- @SerializedName("datasetid")
- private String datasetId = "";
- @SerializedName("recordid")
- private String recordId = "";
- @SerializedName("record_timestamp")
- private String recordTimestamp = "";
- @SerializedName("fields")
- private @Nullable ResponseFieldDTO responseFieldDTO;
-
- public String getDatasetId() {
- return datasetId;
- }
-
- public String getRecordId() {
- return recordId;
- }
-
- public String getRecordTimestamp() {
- return recordTimestamp;
- }
-
- public Optional<ResponseFieldDTO> getResponseFieldDTO() {
- return Optional.ofNullable(responseFieldDTO);
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal.json;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * The {@link Refine} is the Java class used to map the JSON
- * response to the webservice request.
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@NonNullByDefault
-public class Refine {
- @SerializedName("nom_dept")
- private String nomDept = "";
-
- public String getNomDept() {
- return nomDept;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2010-2024 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.meteoalerte.internal.json;
-
-import java.time.ZonedDateTime;
-import java.util.Optional;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * The {@link ResponseFieldDTO} is the Java class used to map the JSON
- * response to the webservice request.
- *
- * @author Gaël L'hopital - Initial contribution
- */
-@NonNullByDefault
-public class ResponseFieldDTO {
- public enum AlertLevel {
- @SerializedName("Vert")
- GREEN("00ff00"),
- @SerializedName("Jaune")
- YELLOW("ffff00"),
- @SerializedName("Orange")
- ORANGE("ef6c00"),
- @SerializedName("Rouge")
- RED("ff0000"),
- UNKNOWN("3d3c3c");
-
- public final String color;
-
- AlertLevel(String color) {
- this.color = color;
- }
- }
-
- @SerializedName("nom_reg")
- private String nomReg = "";
- @SerializedName("typeprev")
- private String typePrev = "";
- @SerializedName("etat_canicule")
- private AlertLevel canicule = AlertLevel.UNKNOWN;
- @SerializedName("nom_dept")
- private String nomDept = "";
- @SerializedName("etat_grand_froid")
- private AlertLevel grandFroid = AlertLevel.UNKNOWN;
- @SerializedName("noversion")
- private String noVersion = "";
- @SerializedName("etat_pluie_inondation")
- private AlertLevel pluieInondation = AlertLevel.UNKNOWN;
- @SerializedName("etat_neige")
- private AlertLevel neige = AlertLevel.UNKNOWN;
- @SerializedName("etat_vent")
- private AlertLevel vent = AlertLevel.UNKNOWN;
- @SerializedName("etat_inondation")
- private AlertLevel inondation = AlertLevel.UNKNOWN;
- @SerializedName("etat_avalanches")
- private AlertLevel avalanches = AlertLevel.UNKNOWN;
- @SerializedName("etat_orage")
- private AlertLevel orage = AlertLevel.UNKNOWN;
- private int echeance;
- @SerializedName("etat_vague_submersion")
- private AlertLevel vagueSubmersion = AlertLevel.UNKNOWN;
- private String dep = "";
- @SerializedName("vigilancecommentaire_texte")
- private String vigilanceComment = "";
- @SerializedName("dateprevue")
- private @Nullable ZonedDateTime datePrevue;
- @SerializedName("dateinsert")
- private @Nullable ZonedDateTime dateInsert;
- @SerializedName("daterun")
- private @Nullable ZonedDateTime dateRun;
-
- public String getVigilanceComment() {
- return vigilanceComment;
- }
-
- public String getNomReg() {
- return nomReg;
- }
-
- public Optional<ZonedDateTime> getDatePrevue() {
- return Optional.ofNullable(datePrevue);
- }
-
- public String getTypePrev() {
- return typePrev;
- }
-
- public AlertLevel getCanicule() {
- return canicule;
- }
-
- public String getNomDept() {
- return nomDept;
- }
-
- public AlertLevel getGrandFroid() {
- return grandFroid;
- }
-
- public String getNoVersion() {
- return noVersion;
- }
-
- public AlertLevel getPluieInondation() {
- return pluieInondation;
- }
-
- public AlertLevel getNeige() {
- return neige;
- }
-
- public AlertLevel getVent() {
- return vent;
- }
-
- public Optional<ZonedDateTime> getDateInsert() {
- return Optional.ofNullable(dateInsert);
- }
-
- public AlertLevel getInondation() {
- return inondation;
- }
-
- public AlertLevel getAvalanches() {
- return avalanches;
- }
-
- public AlertLevel getOrage() {
- return orage;
- }
-
- public int getEcheance() {
- return echeance;
- }
-
- public AlertLevel getVagueSubmersion() {
- return vagueSubmersion;
- }
-
- public String getDep() {
- return dep;
- }
-
- public Optional<ZonedDateTime> getDateRun() {
- return Optional.ofNullable(dateRun);
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<addon:addon id="meteoalerte" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
- xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
-
- <type>binding</type>
- <name>Meteo Alerte Binding</name>
- <description>Retrieves Meteo Alert levels in France</description>
- <connection>cloud</connection>
- <countries>fr</countries>
-
-</addon:addon>
+++ /dev/null
-# add-on
-
-addon.meteoalerte.name = Meteo Alerte Binding
-addon.meteoalerte.description = Retrieves Meteo Alert levels in France
-
-# thing types
-
-thing-type.meteoalerte.department.label = Alertes Département
-thing-type.meteoalerte.department.description = Fournit les niveaux d'alerte météo pour un département.
-thing-type.meteoalerte.department.channel.avalanches-icon.label = Icône Avalanches
-thing-type.meteoalerte.department.channel.canicule-icon.label = Icône Canicule
-thing-type.meteoalerte.department.channel.end-time.label = Fin de validité
-thing-type.meteoalerte.department.channel.grand-froid-icon.label = Icône Grand Froid
-thing-type.meteoalerte.department.channel.inondation-icon.label = Icône Inondation
-thing-type.meteoalerte.department.channel.neige-icon.label = Icône Neige
-thing-type.meteoalerte.department.channel.observation-time.label = Début de validité
-thing-type.meteoalerte.department.channel.orage-icon.label = Icône Orage
-thing-type.meteoalerte.department.channel.pluie-inondation-icon.label = Icône Pluie Inondation
-thing-type.meteoalerte.department.channel.vague-submersion-icon.label = Icône Vague Submersion
-thing-type.meteoalerte.department.channel.vent-icon.label = Icône Vent
-
-# thing types config
-
-thing-type.config.meteoalerte.department.department.label = Département
-thing-type.config.meteoalerte.department.department.description = Nom du département
-thing-type.config.meteoalerte.department.department.option.AIN = Ain
-thing-type.config.meteoalerte.department.department.option.AISNE = Aisne
-thing-type.config.meteoalerte.department.department.option.ALLIER = Allier
-thing-type.config.meteoalerte.department.department.option.ALPES-DE-HAUTE-PROVENCE = Alpes de Haute Provence
-thing-type.config.meteoalerte.department.department.option.ALPES-MARITIMES = Alpes Maritimes
-thing-type.config.meteoalerte.department.department.option.ARDECHE = Ardèche
-thing-type.config.meteoalerte.department.department.option.ARDENNES = Ardennes
-thing-type.config.meteoalerte.department.department.option.ARIEGE = Ariège
-thing-type.config.meteoalerte.department.department.option.AUBE = Aube
-thing-type.config.meteoalerte.department.department.option.AUDE = Aude
-thing-type.config.meteoalerte.department.department.option.AVEYRON = Aveyron
-thing-type.config.meteoalerte.department.department.option.BAS-RHIN = Bas-Rhin
-thing-type.config.meteoalerte.department.department.option.BOUCHES-DU-RHONE = Bouches du Rhône
-thing-type.config.meteoalerte.department.department.option.CALVADOS = Calvados
-thing-type.config.meteoalerte.department.department.option.CANTAL = Cantal
-thing-type.config.meteoalerte.department.department.option.CHARENTE = Charente
-thing-type.config.meteoalerte.department.department.option.CHARENTE-MARITIME = Charente Maritime
-thing-type.config.meteoalerte.department.department.option.CHER = Cher
-thing-type.config.meteoalerte.department.department.option.CORREZE = Corrèze
-thing-type.config.meteoalerte.department.department.option.CORSE-DU-SUD = Corse du Sud
-thing-type.config.meteoalerte.department.department.option.COTE-D'OR = Côte D'Or
-thing-type.config.meteoalerte.department.department.option.COTES-D'ARMOR = Côtes D'Armor
-thing-type.config.meteoalerte.department.department.option.CREUSE = Creuse
-thing-type.config.meteoalerte.department.department.option.DEUX-SEVRES = Deux Sèvres
-thing-type.config.meteoalerte.department.department.option.DORDOGNE = Dordogne
-thing-type.config.meteoalerte.department.department.option.DOUBS = Doubs
-thing-type.config.meteoalerte.department.department.option.DROME = Drôme
-thing-type.config.meteoalerte.department.department.option.ESSONNE = Essonne
-thing-type.config.meteoalerte.department.department.option.EURE = Eure
-thing-type.config.meteoalerte.department.department.option.EURE-ET-LOIR = Eure et Loir
-thing-type.config.meteoalerte.department.department.option.FINISTERE = Finistère
-thing-type.config.meteoalerte.department.department.option.GARD = Gard
-thing-type.config.meteoalerte.department.department.option.GERS = Gers
-thing-type.config.meteoalerte.department.department.option.GIRONDE = Gironde
-thing-type.config.meteoalerte.department.department.option.HAUT-RHIN = Haut-Rhin
-thing-type.config.meteoalerte.department.department.option.HAUTE-CORSE = Haute Corse
-thing-type.config.meteoalerte.department.department.option.HAUTE-GARONNE = Haute Garonne
-thing-type.config.meteoalerte.department.department.option.HAUTE-LOIRE = Haute Loire
-thing-type.config.meteoalerte.department.department.option.HAUTE-MARNE = Haute Marne
-thing-type.config.meteoalerte.department.department.option.HAUTE-SAONE = Haute Saône
-thing-type.config.meteoalerte.department.department.option.HAUTE-SAVOIE = Haute Savoie
-thing-type.config.meteoalerte.department.department.option.HAUTE-VIENNE = Haute Vienne
-thing-type.config.meteoalerte.department.department.option.HAUTES-ALPES = Hautes Alpes
-thing-type.config.meteoalerte.department.department.option.HAUTES-PYRENEES = Hautes Pyrénées
-thing-type.config.meteoalerte.department.department.option.HAUTS-DE-SEINE = Hauts de Seine
-thing-type.config.meteoalerte.department.department.option.HERAULT = Hérault
-thing-type.config.meteoalerte.department.department.option.ILLE-ET-VILAINE = Ille et Vilaine
-thing-type.config.meteoalerte.department.department.option.INDRE = Indre
-thing-type.config.meteoalerte.department.department.option.INDRE-ET-LOIRE = Indre et Loire
-thing-type.config.meteoalerte.department.department.option.ISERE = Isère
-thing-type.config.meteoalerte.department.department.option.JURA = Jura
-thing-type.config.meteoalerte.department.department.option.LANDES = Landes
-thing-type.config.meteoalerte.department.department.option.LOIR-ET-CHER = Loir et Cher
-thing-type.config.meteoalerte.department.department.option.LOIRE = Loire
-thing-type.config.meteoalerte.department.department.option.LOIRE-ATLANTIQUE = Loire Atlantique
-thing-type.config.meteoalerte.department.department.option.LOIRET = Loiret
-thing-type.config.meteoalerte.department.department.option.LOT = Lot
-thing-type.config.meteoalerte.department.department.option.LOT-ET-GARONNE = Lot et Garonne
-thing-type.config.meteoalerte.department.department.option.LOZERE = Lozère
-thing-type.config.meteoalerte.department.department.option.MAINE-ET-LOIRE = Maine et Loire
-thing-type.config.meteoalerte.department.department.option.MANCHE = Manche
-thing-type.config.meteoalerte.department.department.option.MARNE = Marne
-thing-type.config.meteoalerte.department.department.option.MAYENNE = Mayenne
-thing-type.config.meteoalerte.department.department.option.MEURTHE-ET-MOSELLE = Meurthe et Moselle
-thing-type.config.meteoalerte.department.department.option.MEUSE = Meuse
-thing-type.config.meteoalerte.department.department.option.MORBIHAN = Morbihan
-thing-type.config.meteoalerte.department.department.option.MOSELLE = Moselle
-thing-type.config.meteoalerte.department.department.option.NIEVRE = Nièvre
-thing-type.config.meteoalerte.department.department.option.NORD = Nord
-thing-type.config.meteoalerte.department.department.option.OISE = Oise
-thing-type.config.meteoalerte.department.department.option.ORNE = Orne
-thing-type.config.meteoalerte.department.department.option.PARIS = Paris
-thing-type.config.meteoalerte.department.department.option.PAS-DE-CALAIS = Pas de Calais
-thing-type.config.meteoalerte.department.department.option.PUY-DE-DOME = Puy de Dôme
-thing-type.config.meteoalerte.department.department.option.PYRENEES-ATLANTIQUES = Pyrénées Atlantiques
-thing-type.config.meteoalerte.department.department.option.PYRENEES-ORIENTALES = Pyrénées Orientales
-thing-type.config.meteoalerte.department.department.option.RHONE = Rhône
-thing-type.config.meteoalerte.department.department.option.SAONE-ET-LOIRE = Saône et Loire
-thing-type.config.meteoalerte.department.department.option.SARTHE = Sarthe
-thing-type.config.meteoalerte.department.department.option.SAVOIE = Savoie
-thing-type.config.meteoalerte.department.department.option.SEINE-ET-MARNE = Seine et Marne
-thing-type.config.meteoalerte.department.department.option.SEINE-MARITIME = Seine Maritime
-thing-type.config.meteoalerte.department.department.option.SEINE-SAINT-DENIS = Seine Saint Denis
-thing-type.config.meteoalerte.department.department.option.SOMME = Somme
-thing-type.config.meteoalerte.department.department.option.TARN = Tarn
-thing-type.config.meteoalerte.department.department.option.TARN-ET-GARONNE = Tarn et Garonne
-thing-type.config.meteoalerte.department.department.option.TERRITOIRE\ DE\ BELFORT = Territoire de Belfort
-thing-type.config.meteoalerte.department.department.option.VAL-D'OISE = Val D'Oise
-thing-type.config.meteoalerte.department.department.option.VAL-DE-MARNE = Val de Marne
-thing-type.config.meteoalerte.department.department.option.VAR = Var
-thing-type.config.meteoalerte.department.department.option.VAUCLUSE = Vaucluse
-thing-type.config.meteoalerte.department.department.option.VENDEE = Vendée
-thing-type.config.meteoalerte.department.department.option.VIENNE = Vienne
-thing-type.config.meteoalerte.department.department.option.VOSGES = Vosges
-thing-type.config.meteoalerte.department.department.option.YONNE = Yonne
-thing-type.config.meteoalerte.department.department.option.YVELINES = Yvelines
-thing-type.config.meteoalerte.department.refresh.label = Fréquence de rafraichissement
-thing-type.config.meteoalerte.department.refresh.description = Période d'actualisation des données en minutes.
-
-# channel types
-
-channel-type.meteoalerte.avalanches.label = Avalanches
-channel-type.meteoalerte.avalanches.description = Niveau d'alerte aux avalanches
-channel-type.meteoalerte.avalanches.state.option.0 = Vert
-channel-type.meteoalerte.avalanches.state.option.1 = Jaune
-channel-type.meteoalerte.avalanches.state.option.2 = Orange
-channel-type.meteoalerte.avalanches.state.option.3 = Rouge
-channel-type.meteoalerte.canicule.label = Canicule
-channel-type.meteoalerte.canicule.description = Niveau d'alerte aux fortes températures
-channel-type.meteoalerte.canicule.state.option.0 = Vert
-channel-type.meteoalerte.canicule.state.option.1 = Jaune
-channel-type.meteoalerte.canicule.state.option.2 = Orange
-channel-type.meteoalerte.canicule.state.option.3 = Rouge
-channel-type.meteoalerte.comment.label = Commentaire
-channel-type.meteoalerte.condition-icon.label = Pictogramme
-channel-type.meteoalerte.condition-icon.description = Pictogramme associé au niveau d'alerte.
-channel-type.meteoalerte.grand-froid.label = Grand Froid
-channel-type.meteoalerte.grand-froid.description = Niveau d'alerte aux températures négatives
-channel-type.meteoalerte.grand-froid.state.option.0 = Vert
-channel-type.meteoalerte.grand-froid.state.option.1 = Jaune
-channel-type.meteoalerte.grand-froid.state.option.2 = Orange
-channel-type.meteoalerte.grand-froid.state.option.3 = Rouge
-channel-type.meteoalerte.inondation.label = Inondation
-channel-type.meteoalerte.inondation.description = Niveau d'alerte aux inondations
-channel-type.meteoalerte.inondation.state.option.0 = Vert
-channel-type.meteoalerte.inondation.state.option.1 = Jaune
-channel-type.meteoalerte.inondation.state.option.2 = Orange
-channel-type.meteoalerte.inondation.state.option.3 = Rouge
-channel-type.meteoalerte.neige.label = Neige
-channel-type.meteoalerte.neige.description = Niveau d'alerte aux évènements neigeux
-channel-type.meteoalerte.neige.state.option.0 = Vert
-channel-type.meteoalerte.neige.state.option.1 = Jaune
-channel-type.meteoalerte.neige.state.option.2 = Orange
-channel-type.meteoalerte.neige.state.option.3 = Rouge
-channel-type.meteoalerte.orage.label = Orage
-channel-type.meteoalerte.orage.description = Niveau d'alerte aux évènements orageux
-channel-type.meteoalerte.orage.state.option.0 = Vert
-channel-type.meteoalerte.orage.state.option.1 = Jaune
-channel-type.meteoalerte.orage.state.option.2 = Orange
-channel-type.meteoalerte.orage.state.option.3 = Rouge
-channel-type.meteoalerte.pluie-inondation.label = Pluie Inondation
-channel-type.meteoalerte.pluie-inondation.description = Niveau d'alerte aux inondations causées par les précipitations
-channel-type.meteoalerte.pluie-inondation.state.option.0 = Vert
-channel-type.meteoalerte.pluie-inondation.state.option.1 = Jaune
-channel-type.meteoalerte.pluie-inondation.state.option.2 = Orange
-channel-type.meteoalerte.pluie-inondation.state.option.3 = Rouge
-channel-type.meteoalerte.timestamp.label = Heure d'observation
-channel-type.meteoalerte.vague-submersion.label = Vague Submersion
-channel-type.meteoalerte.vague-submersion.description = Niveau d'alerte aux vagues submersion
-channel-type.meteoalerte.vague-submersion.state.option.0 = Vert
-channel-type.meteoalerte.vague-submersion.state.option.1 = Jaune
-channel-type.meteoalerte.vague-submersion.state.option.2 = Orange
-channel-type.meteoalerte.vague-submersion.state.option.3 = Rouge
-channel-type.meteoalerte.vent.label = Vent
-channel-type.meteoalerte.vent.description = Niveau d'alerte aux évènements éoliens
-channel-type.meteoalerte.vent.state.option.0 = Vert
-channel-type.meteoalerte.vent.state.option.1 = Jaune
-channel-type.meteoalerte.vent.state.option.2 = Orange
-channel-type.meteoalerte.vent.state.option.3 = Rouge
-
-# iconprovider
-
-iconset.label = Météo Alerte Icons
-iconset.description = Icons illustrating weather events provided by Météo Alerte
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<thing:thing-descriptions bindingId="meteoalerte"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
- xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
-
- <thing-type id="department">
- <label>Alertes Département</label>
- <description>Fournit les niveaux d'alerte météo pour un département.</description>
-
- <channels>
- <channel id="vague-submersion" typeId="vague-submersion"/>
- <channel id="vent" typeId="vent"/>
- <channel id="pluie-inondation" typeId="pluie-inondation"/>
- <channel id="orage" typeId="orage"/>
- <channel id="inondation" typeId="inondation"/>
- <channel id="neige" typeId="neige"/>
- <channel id="canicule" typeId="canicule"/>
- <channel id="grand-froid" typeId="grand-froid"/>
- <channel id="avalanches" typeId="avalanches"/>
- <channel id="vague-submersion-icon" typeId="condition-icon">
- <label>Icône Vague Submersion</label>
- </channel>
- <channel id="vent-icon" typeId="condition-icon">
- <label>Icône Vent</label>
- </channel>
- <channel id="pluie-inondation-icon" typeId="condition-icon">
- <label>Icône Pluie Inondation</label>
- </channel>
- <channel id="orage-icon" typeId="condition-icon">
- <label>Icône Orage</label>
- </channel>
- <channel id="inondation-icon" typeId="condition-icon">
- <label>Icône Inondation</label>
- </channel>
- <channel id="neige-icon" typeId="condition-icon">
- <label>Icône Neige</label>
- </channel>
- <channel id="canicule-icon" typeId="condition-icon">
- <label>Icône Canicule</label>
- </channel>
- <channel id="grand-froid-icon" typeId="condition-icon">
- <label>Icône Grand Froid</label>
- </channel>
- <channel id="avalanches-icon" typeId="condition-icon">
- <label>Icône Avalanches</label>
- </channel>
- <channel id="comment" typeId="comment"/>
- <channel id="observation-time" typeId="timestamp">
- <label>Début de validité</label>
- </channel>
- <channel id="end-time" typeId="timestamp">
- <label>Fin de validité</label>
- </channel>
- </channels>
-
- <properties>
- <property name="thingTypeVersion">1</property>
- </properties>
-
- <config-description>
- <parameter name="department" type="text" required="true">
- <label>Département</label>
- <description>Nom du département</description>
- <options>
- <option value="AIN">Ain</option>
- <option value="AISNE">Aisne</option>
- <option value="ALLIER">Allier</option>
- <option value="ALPES-DE-HAUTE-PROVENCE">Alpes de Haute Provence</option>
- <option value="ALPES-MARITIMES">Alpes Maritimes</option>
- <option value="ARDECHE">Ardèche</option>
- <option value="ARDENNES">Ardennes</option>
- <option value="ARIEGE">Ariège</option>
- <option value="AUBE">Aube</option>
- <option value="AUDE">Aude</option>
- <option value="AVEYRON">Aveyron</option>
- <option value="BAS-RHIN">Bas-Rhin</option>
- <option value="BOUCHES-DU-RHONE">Bouches du Rhône</option>
- <option value="CALVADOS">Calvados</option>
- <option value="CANTAL">Cantal</option>
- <option value="CHARENTE">Charente</option>
- <option value="CHARENTE-MARITIME">Charente Maritime</option>
- <option value="CHER">Cher</option>
- <option value="CORREZE">Corrèze</option>
- <option value="CORSE-DU-SUD">Corse du Sud</option>
- <option value="COTE-D'OR">Côte D'Or</option>
- <option value="COTES-D'ARMOR">Côtes D'Armor</option>
- <option value="CREUSE">Creuse</option>
- <option value="DEUX-SEVRES">Deux Sèvres</option>
- <option value="DORDOGNE">Dordogne</option>
- <option value="DOUBS">Doubs</option>
- <option value="DROME">Drôme</option>
- <option value="ESSONNE">Essonne</option>
- <option value="EURE">Eure</option>
- <option value="EURE-ET-LOIR">Eure et Loir</option>
- <option value="FINISTERE">Finistère</option>
- <option value="GARD">Gard</option>
- <option value="GERS">Gers</option>
- <option value="GIRONDE">Gironde</option>
- <option value="HAUT-RHIN">Haut-Rhin</option>
- <option value="HAUTE-CORSE">Haute Corse</option>
- <option value="HAUTE-GARONNE">Haute Garonne</option>
- <option value="HAUTE-LOIRE">Haute Loire</option>
- <option value="HAUTE-MARNE">Haute Marne</option>
- <option value="HAUTE-SAONE">Haute Saône</option>
- <option value="HAUTE-SAVOIE">Haute Savoie</option>
- <option value="HAUTE-VIENNE">Haute Vienne</option>
- <option value="HAUTES-ALPES">Hautes Alpes</option>
- <option value="HAUTES-PYRENEES">Hautes Pyrénées</option>
- <option value="HAUTS-DE-SEINE">Hauts de Seine</option>
- <option value="HERAULT">Hérault</option>
- <option value="ILLE-ET-VILAINE">Ille et Vilaine</option>
- <option value="INDRE">Indre</option>
- <option value="INDRE-ET-LOIRE">Indre et Loire</option>
- <option value="ISERE">Isère</option>
- <option value="JURA">Jura</option>
- <option value="LANDES">Landes</option>
- <option value="LOIR-ET-CHER">Loir et Cher</option>
- <option value="LOIRE">Loire</option>
- <option value="LOIRE-ATLANTIQUE">Loire Atlantique</option>
- <option value="LOIRET">Loiret</option>
- <option value="LOT">Lot</option>
- <option value="LOT-ET-GARONNE">Lot et Garonne</option>
- <option value="LOZERE">Lozère</option>
- <option value="MAINE-ET-LOIRE">Maine et Loire</option>
- <option value="MANCHE">Manche</option>
- <option value="MARNE">Marne</option>
- <option value="MAYENNE">Mayenne</option>
- <option value="MEURTHE-ET-MOSELLE">Meurthe et Moselle</option>
- <option value="MEUSE">Meuse</option>
- <option value="MORBIHAN">Morbihan</option>
- <option value="MOSELLE">Moselle</option>
- <option value="NIEVRE">Nièvre</option>
- <option value="NORD">Nord</option>
- <option value="OISE">Oise</option>
- <option value="ORNE">Orne</option>
- <option value="PARIS">Paris</option>
- <option value="PAS-DE-CALAIS">Pas de Calais</option>
- <option value="PUY-DE-DOME">Puy de Dôme</option>
- <option value="PYRENEES-ATLANTIQUES">Pyrénées Atlantiques</option>
- <option value="PYRENEES-ORIENTALES">Pyrénées Orientales</option>
- <option value="RHONE">Rhône</option>
- <option value="SAONE-ET-LOIRE">Saône et Loire</option>
- <option value="SARTHE">Sarthe</option>
- <option value="SAVOIE">Savoie</option>
- <option value="SEINE-ET-MARNE">Seine et Marne</option>
- <option value="SEINE-MARITIME">Seine Maritime</option>
- <option value="SEINE-SAINT-DENIS">Seine Saint Denis</option>
- <option value="SOMME">Somme</option>
- <option value="TARN">Tarn</option>
- <option value="TARN-ET-GARONNE">Tarn et Garonne</option>
- <option value="TERRITOIRE DE BELFORT">Territoire de Belfort</option>
- <option value="VAL-D'OISE">Val D'Oise</option>
- <option value="VAL-DE-MARNE">Val de Marne</option>
- <option value="VAR">Var</option>
- <option value="VAUCLUSE">Vaucluse</option>
- <option value="VENDEE">Vendée</option>
- <option value="VIENNE">Vienne</option>
- <option value="VOSGES">Vosges</option>
- <option value="YONNE">Yonne</option>
- <option value="YVELINES">Yvelines</option>
- </options>
- <limitToOptions>true</limitToOptions>
- </parameter>
- <parameter name="refresh" type="integer" min="1" required="true" unit="min">
- <label>Fréquence de rafraichissement</label>
- <description>Période d'actualisation des données en minutes.</description>
- <default>1440</default>
- </parameter>
- </config-description>
- </thing-type>
-
- <channel-type id="vent">
- <item-type>Number</item-type>
- <label>Vent</label>
- <description>Niveau d'alerte aux évènements éoliens</description>
- <category>oh:meteoalerte:vent</category>
- <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="orage">
- <item-type>Number</item-type>
- <label>Orage</label>
- <description>Niveau d'alerte aux évènements orageux</description>
- <category>oh:meteoalerte:orage</category>
- <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="inondation">
- <item-type>Number</item-type>
- <label>Inondation</label>
- <description>Niveau d'alerte aux inondations</description>
- <category>oh:meteoalerte:inondation</category>
- <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="neige">
- <item-type>Number</item-type>
- <label>Neige</label>
- <description>Niveau d'alerte aux évènements neigeux</description>
- <category>oh:meteoalerte:neige</category>
- <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="canicule">
- <item-type>Number</item-type>
- <label>Canicule</label>
- <description>Niveau d'alerte aux fortes températures</description>
- <category>oh:meteoalerte:canicule</category>
- <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="grand-froid">
- <item-type>Number</item-type>
- <label>Grand Froid</label>
- <description>Niveau d'alerte aux températures négatives</description>
- <category>oh:meteoalerte:grand-froid</category>
- <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="avalanches">
- <item-type>Number</item-type>
- <label>Avalanches</label>
- <description>Niveau d'alerte aux avalanches</description>
- <category>oh:meteoalerte:avalanches</category>
- <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="vague-submersion">
- <item-type>Number</item-type>
- <label>Vague Submersion</label>
- <description>Niveau d'alerte aux vagues submersion</description>
- <category>oh:meteoalerte:vague-submersion</category>
- <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="pluie-inondation">
- <item-type>Number</item-type>
- <label>Pluie Inondation</label>
- <description>Niveau d'alerte aux inondations causées par les précipitations</description>
- <category>oh:meteoalerte:pluie-inondation</category>
- <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>
- <category>text</category>
- <state readOnly="true" pattern="%s"/>
- </channel-type>
-
- <channel-type id="timestamp" advanced="true">
- <item-type>DateTime</item-type>
- <label>Heure d'observation</label>
- <category>time</category>
- <state readOnly="true"/>
- </channel-type>
-
- <channel-type id="condition-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>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
- xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
-
- <thing-type uid="meteoalerte:department">
-
- <instruction-set targetVersion="1">
- <update-channel id="vague-submersion">
- <type>meteoalerte:vague-submersion</type>
- </update-channel>
- <update-channel id="vent">
- <type>meteoalerte:vent</type>
- </update-channel>
- <update-channel id="pluie-inondation">
- <type>meteoalerte:pluie-inondation</type>
- </update-channel>
- <update-channel id="orage">
- <type>meteoalerte:orage</type>
- </update-channel>
- <update-channel id="inondation">
- <type>meteoalerte:inondation</type>
- </update-channel>
- <update-channel id="neige">
- <type>meteoalerte:neige</type>
- </update-channel>
- <update-channel id="canicule">
- <type>meteoalerte:canicule</type>
- </update-channel>
- <update-channel id="grand-froid">
- <type>meteoalerte:grand-froid</type>
- </update-channel>
- <update-channel id="avalanches">
- <type>meteoalerte:avalanches</type>
- </update-channel>
- </instruction-set>
-
- </thing-type>
-
-</update:update-descriptions>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
- <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
- <g transform="matrix(0.095654, 0, 0, 0.103801, 7.65905, -0.7645)" style="">
- <g>
- <path style="fill:#9B5C5C;" d="M277.259,58.637c-11.695-20.344-30.835-20.344-42.53,0L4.978,432.587 c-11.695,20.342-2.07,36.966,21.398,36.966h459.235c23.468,0,33.093-16.624,21.405-36.966L277.259,58.637z"/>
- <path style="fill:#9B5C5C;" d="M277.259,57.683c-11.695-20.328-30.835-20.328-42.53,0l-23.538,59.732l-32.538,31.78L4.978,432.587 c-11.695,20.342-2.07,36.966,21.398,36.966h459.235c23.468,0,33.093-16.624,21.405-36.966l-56.124-91.592l-84.06-104.052 L277.259,57.683z"/>
- </g>
- <g>
- <path style="fill:#CBD0D8;" d="M426.629,226.272c-23.562,0-42.671,19.108-42.671,42.671c0,23.554,19.109,42.646,42.671,42.646 c23.545,0,42.654-19.093,42.654-42.646C469.283,245.381,450.174,226.272,426.629,226.272L426.629,226.272z"/>
- <path style="fill:#CBD0D8;" d="M394.63,226.272c0,5.89-4.766,10.671-10.672,10.671c-5.875,0-10.656-4.781-10.656-10.671 c0-5.875,4.781-10.656,10.656-10.656C389.864,215.616,394.63,220.397,394.63,226.272z"/>
- <path style="fill:#CBD0D8;" d="M426.629,204.944c0,5.891-4.781,10.672-10.671,10.672c-5.891,0-10.656-4.781-10.656-10.672 s4.766-10.655,10.656-10.655C421.848,194.289,426.629,199.054,426.629,204.944z"/>
- <path style="fill:#CBD0D8;" d="M383.958,183.617c0,5.891-4.766,10.672-10.656,10.672s-10.656-4.781-10.656-10.672 s4.766-10.656,10.656-10.656S383.958,177.726,383.958,183.617z"/>
- <path style="fill:#CBD0D8;" d="M351.974,151.634c0,5.891-4.766,10.655-10.672,10.655c-5.874,0-10.655-4.765-10.655-10.655 s4.781-10.671,10.655-10.671C347.209,140.963,351.974,145.744,351.974,151.634z"/>
- </g>
- <path style="fill:#E6E9ED;" d="M 273.368 152.384 C 274.649 151.868 275.993 151.634 277.321 151.634 C 280.992 151.634 284.554 153.54 286.523 156.884 C 286.523 156.884 355.865 257.194 381.786 300.341 C 407.708 343.495 450.892 341.027 450.892 341.027 L 277.259 57.683 C 265.564 37.355 246.424 37.355 234.729 57.683 L 178.653 149.196 C 178.653 149.196 210.879 171.539 225.503 171.539 C 240.126 171.539 273.368 152.384 273.368 152.384 Z"/>
- </g>
-</svg>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
- <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
- <g fill="#dae1e4">
- <circle cx="32" cy="55" r="9" />
- <circle cx="32" cy="6" r="6" />
- </g>
- <circle cx="32" cy="6" r="5" fill="#d20014" />
- <path d="m26 6h12v50h-12z" fill="#dae1e4" />
- <g fill="#d20014">
- <path d="m27 6h10v48.94h-10z" />
- <circle cx="32" cy="55" r="8" />
- </g>
- <g fill="#fff">
- <path d="m33 9h5v2h-5z" />
- <path d="m33 17h5v2h-5z" />
- <path d="m33 25h5v2h-5z" />
- <path d="m33 33h5v2h-5z" />
- <path d="m33 41h5v2h-5z" />
- </g>
-</svg>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
- <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
- <circle cx="32" cy="6" r="6" fill="#dae1e4" />
- <circle cx="32" cy="6" r="5" fill="#c4cacc" />
- <path d="m26 6h12v50h-12z" fill="#dae1e4" />
- <path d="m27 6h10v48.94h-10z" fill="#c4cacc" />
- <circle cx="32" cy="55" r="9" fill="#dae1e4" />
- <g fill="#2e7de5">
- <circle cx="32" cy="55" r="8" />
- <path d="m27 39h10v12h-10z" />
- </g>
- <g fill="#fff">
- <path d="m33 9h5v2h-5z" />
- <path d="m33 17h5v2h-5z" />
- <path d="m33 25h5v2h-5z" />
- <path d="m33 33h5v2h-5z" />
- <path d="m33 41h5v2h-5z" />
- </g>
-</svg>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
- <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
- <path fill="#F8EFE0" d="M 11.018 52.475 L 11.018 31.819 C 7.317 33.065 4.779 29.687 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 51.937 51.358 C 43.944 54.785 42.3 46.755 42.28 46.918 C 41.461 53.613 28.847 53.227 26.809 48.767 C 26.439 47.958 26.67 47.804 26.141 47.766 C 23.045 47.544 22.868 55.347 11.018 52.475 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
- <path fill="#D93133" d="M 11.018 31.819 C 10.054 32.144 9.151 32.151 8.401 31.927 C 7.816 31.754 7.322 31.444 6.959 31.043 C 6.596 30.643 6.366 30.156 6.295 29.618 C 6.188 28.785 6.472 27.843 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 49.63 30.982 C 49.63 30.618 33.464 19.43 31.679 18.213 C 29.788 19.473 13.326 30.571 13.326 31.04 L 11.018 31.819 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
- <path fill="#313A58" d="M 31.595 25.496 C 33.228 25.496 34.711 26.081 35.784 27.021 C 36.861 27.963 37.526 29.076 37.526 30.503 L 37.526 35.325 L 25.662 35.325 L 25.662 30.503 C 25.662 29.073 26.33 27.961 27.404 27.021 C 28.479 26.081 29.963 25.496 31.595 25.496 Z" style=""/>
- <path fill="#ABB9BC" d="M 32.111 31.421 L 32.111 34.426 L 36.496 34.426 L 36.496 31.421 L 32.111 31.421 Z M 32.111 26.424 L 32.111 30.517 L 36.496 30.517 L 36.496 30.505 C 36.496 29.326 35.945 28.439 35.056 27.661 C 34.282 26.983 33.252 26.529 32.111 26.424 Z M 31.079 30.517 L 31.079 26.424 C 29.936 26.531 28.909 26.983 28.134 27.661 C 27.245 28.439 26.694 29.326 26.694 30.505 L 26.694 30.517 L 31.079 30.517 Z M 31.079 34.423 L 31.079 31.421 L 26.694 31.421 L 26.694 34.426 L 31.079 34.426 L 31.079 34.423 Z" style=""/>
- <path fill="#313A58" d="M 51.92 31.732 L 49.64 30.959 L 49.64 52.389 L 51.92 52.389 L 51.92 31.732 Z M 10.908 31.819 L 13.189 31.046 L 13.189 52.476 L 10.908 52.476 L 10.908 31.819 Z" style=""/>
- <path d="M 11.097 51.603 C 13.269 52.586 15.988 52.276 18.451 51.315 C 21.367 50.176 23.866 48.168 24.668 46.318 C 24.9 45.781 25.509 45.54 26.029 45.779 C 26.259 45.885 26.444 46.075 26.547 46.312 C 27.432 48.152 28.886 49.487 30.554 50.246 C 31.623 50.733 32.775 50.983 33.918 50.978 C 35.051 50.973 36.18 50.717 37.211 50.195 C 38.688 49.446 39.974 48.13 40.802 46.195 C 41.031 45.656 41.641 45.412 42.163 45.649 C 42.416 45.764 42.614 45.978 42.711 46.245 C 43.106 47.121 43.54 47.869 44.009 48.496 C 45.11 49.969 46.402 50.756 47.805 50.981 C 49.259 51.215 50.874 50.868 52.56 50.07 C 53.763 49.501 55 48.701 56.239 47.714 L 57.499 49.397 C 56.142 50.478 54.77 51.363 53.416 52.004 C 51.373 52.971 49.365 53.383 47.49 53.082 C 45.567 52.773 43.824 51.731 42.377 49.796 C 42.148 49.488 41.933 49.17 41.734 48.842 C 40.756 50.32 39.505 51.399 38.116 52.103 C 36.799 52.772 35.361 53.098 33.918 53.104 C 32.484 53.109 31.046 52.799 29.722 52.197 C 28.122 51.468 26.677 50.311 25.588 48.764 C 24.183 50.57 21.811 52.279 19.178 53.307 C 16.265 54.444 12.989 54.782 10.273 53.553 L 11.097 51.603 Z" style="fill: rgb(30, 130, 255);"/>
- <path d="M 10.92 57.018 C 13.092 58.001 15.811 57.691 18.274 56.73 C 21.19 55.591 23.689 53.583 24.491 51.733 C 24.723 51.196 25.332 50.955 25.852 51.194 C 26.082 51.3 26.267 51.49 26.37 51.727 C 27.255 53.567 28.709 54.902 30.377 55.661 C 31.446 56.148 32.598 56.398 33.741 56.393 C 34.874 56.388 36.003 56.132 37.034 55.61 C 38.511 54.861 39.797 53.545 40.625 51.61 C 40.854 51.071 41.464 50.827 41.986 51.064 C 42.239 51.179 42.437 51.393 42.534 51.66 C 42.929 52.536 43.363 53.284 43.832 53.911 C 44.933 55.384 46.225 56.171 47.628 56.396 C 49.082 56.63 50.697 56.283 52.383 55.485 C 53.586 54.916 54.823 54.116 56.062 53.129 L 57.322 54.812 C 55.965 55.893 54.593 56.778 53.239 57.419 C 51.196 58.386 49.188 58.798 47.313 58.497 C 45.39 58.188 43.647 57.146 42.2 55.211 C 41.971 54.903 41.756 54.585 41.557 54.257 C 40.579 55.735 39.328 56.814 37.939 57.518 C 36.622 58.187 35.184 58.513 33.741 58.519 C 32.307 58.524 30.869 58.214 29.545 57.612 C 27.945 56.883 26.5 55.726 25.411 54.179 C 24.006 55.985 21.634 57.694 19.001 58.722 C 16.088 59.859 12.812 60.197 10.096 58.968 L 10.92 57.018 Z" style="fill: rgb(30, 130, 255);"/>
-</svg>
\ No newline at end of file
+++ /dev/null
-<svg xmlns="http://www.w3.org/2000/svg" height="600" width="600" data-name="Calque 1">
- <path fill="#005892" d="M0 0h600v600H0z" />
- <rect x="220.481" y="111.57" width="159.038" height="159.038" rx="12.759" ry="12.759" fill="#fff" />
- <path fill="#005891" d="M334.557 134.05l17.013 17.697-24.152 6.152z" />
- <path
- d="M357.95 191.089a57.646 57.646 0 00-10.178-32.81l-5.164 1.974a56.05 56.05 0 0110.253 30.836 53.165 53.165 0 01-45.57 52.329 210.152 210.152 0 01-1.747-104.81 55.443 55.443 0 0119.747 6l1.291-4.861a57.57 57.57 0 00-19.747-6.152 150.684 150.684 0 018.127-22.025h-7.595a164.05 164.05 0 00-7.595 21.645 57.95 57.95 0 000 115.823h1.975c1.975 7.063 4.253 14.278 7.063 21.646h7.063c-2.886-7.595-5.392-15.19-7.595-22.254a57.95 57.95 0 0049.671-57.341z"
- fill="#005891" />
- <path d="M298.633 130.405h-7.063" fill="#fff" />
- <g fill="#fff">
- <path
- d="M123.418 315.342h22.025l14.582 44.126 14.05-44.126h22.102l7.975 76.48H182.05l-3.266-38.278-11.317 38.279h-15.873l-11.317-38.279-4.48 38.279H114zM268.405 372.608h-34.709v-10.254h26.279V346.33H233.24v-11.544h35.164v-19.443h-56.278v76.48h56.278zM403.975 372.608H369.19v-10.254h26.278V346.33h-26.734v-11.544h35.24v-19.443H347.62v76.48h56.355zM297.038 391.823h21.19v-57.038h18.76v-19.443h-59.165v19.443h19.215zM448.101 314.658a37.975 37.975 0 1037.975 37.975 37.975 37.975 0 00-37.975-37.975zm0 57.494a19.443 19.443 0 1119.443-19.443 19.443 19.443 0 01-19.443 19.443zM134.962 464.127h23.696v-14.81h-23.696v-14.963h30.684v-18.607H114v72.607h20.962zM213.57 458.81s10.936-1.215 10.936-21.19a19.519 19.519 0 00-18.835-21.873h-34.86v72.607h17.695V461.62h6.532l11.165 26.734h20.886zm-11.848-11.544h-13.52v-17.469h13.52a9.494 9.494 0 010 17.469zM274.025 415.747h-16.253l-27.418 72.607h20.735l5.392-13.519h19.975l4.557 13.52h19.822zm-15.19 45.114l6.988-19.52 6.987 19.52zM321.494 449.316l26.05 39.038h16.785v-72.607h-18.911v42.456l-24.152-42.456h-18.38v72.607h18.608zM418.253 465.038a18.38 18.38 0 11-.987-26.43l11.848-13.292a36.076 36.076 0 100 53.773zM486 470.127h-33.038v-9.722h24.987V445.14h-25.443v-10.936H486V415.67h-53.544v72.76H486z" />
- </g>
-</svg>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
- <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
- <path
- d="m32 2.5c.98 0 1.76.79 1.76 1.76v8.25l2.82-4.09c.35-.5.9-.77 1.47-.76.34 0 .68.11.98.31.8.55 1.01 1.65.45 2.45l-5.73 8.31v3.56 6.66l8.85-5.11 4.33-9.11c.42-.88 1.47-1.25 2.35-.84.33.16.59.4.76.7.29.49.33 1.1.07 1.65l-2.13 4.49 7.15-4.13c.85-.49 1.92-.2 2.41.65.49.85.2 1.92-.65 2.41l-7.15 4.13 4.96.4c.61.05 1.12.4 1.4.89.17.3.25.64.22 1.01-.08.97-.92 1.69-1.9 1.62l-10.06-.8-8.84 5.09 5.77 3.33 3.08 1.78 10.06-.8c.97-.08 1.82.64 1.9 1.62.03.36-.05.71-.22 1.01-.28.49-.79.84-1.4.89l-4.96.4 7.15 4.13c.85.49 1.13 1.56.65 2.41-.49.85-1.56 1.13-2.41.64l-7.15-4.13 2.13 4.49c.26.55.22 1.17-.07 1.65-.17.29-.43.54-.76.69-.88.42-1.93.05-2.35-.83l-4.33-9.11-8.85-5.11v6.66 3.56l5.73 8.31c.55.8.35 1.9-.45 2.45-.3.21-.64.31-.98.31-.57.01-1.12-.26-1.47-.76l-2.82-4.09v8.25c0 .98-.79 1.76-1.76 1.76-.98 0-1.76-.79-1.76-1.76v-8.25l-2.82 4.09c-.35.5-.9.77-1.47.76-.34 0-.68-.11-.98-.31-.8-.55-1.01-1.65-.45-2.45l5.73-8.31v-3.56-6.66l-5.77 3.33-3.08 1.78-4.33 9.11c-.42.88-1.47 1.25-2.35.83-.33-.16-.59-.4-.76-.69-.29-.49-.33-1.1-.07-1.65l2.14-4.49-7.15 4.13c-.85.49-1.92.2-2.41-.64-.49-.85-.2-1.92.64-2.41l7.15-4.13-4.96-.4c-.61-.05-1.12-.4-1.4-.89-.17-.3-.25-.64-.22-1.01.08-.97.92-1.69 1.9-1.62l10.06.8 3.08-1.78 5.75-3.33-8.85-5.11-10.06.8c-.97.08-1.82-.64-1.9-1.62-.03-.36.05-.71.22-1.01.28-.49.79-.84 1.4-.89l4.96-.4-7.15-4.11c-.85-.49-1.13-1.56-.64-2.41.49-.85 1.56-1.13 2.41-.65l7.15 4.13-2.14-4.49c-.26-.55-.22-1.17.07-1.65.17-.29.43-.54.76-.7.88-.42 1.93-.05 2.35.84l4.33 9.11 8.85 5.11v-6.66-3.56l-5.73-8.31c-.55-.8-.35-1.9.45-2.45.3-.21.64-.31.98-.31.57-.01 1.12.26 1.47.76l2.82 4.09v-8.25c.01-.97.79-1.76 1.77-1.76"
- fill="#dae1e4" />
-</svg>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
- <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
- <g transform="matrix(0.109429, 0, 0, 0.095795, 3.683853, 5.87504)" style="">
- <polygon style="fill:#FFDA44;" points="225.584 244.867 174.304 380.884 268.543 380.884 209.837 509.421 367.316 333.616 271.782 333.616 303.985 244.867"/>
- <polygon style="fill:#CCA400;" points="304.519 244.867 226.118 244.867 207.482 294.3 286.581 294.3"/>
- <path style="fill:#B8D6FD;" d="M 459.559 266.555 C 488.522 266.555 512.001 243.077 512.001 214.113 C 512.001 185.149 488.523 161.671 459.559 161.671 C 450.829 161.671 442.605 163.816 435.364 167.589 C 428.157 153.316 416.099 141.917 401.341 135.574 C 401.341 135.443 401.351 135.316 401.351 135.185 C 401.351 62.632 342.535 3.817 269.982 3.817 C 209.899 3.817 159.273 44.169 143.634 99.239 C 109.041 105.309 81.724 132.452 75.398 166.956 C 68.464 163.574 60.675 161.671 52.44 161.671 C 23.479 161.672 0 185.15 0 214.114 C 0 243.078 23.479 266.556 52.442 266.556 L 459.559 266.556 L 459.559 266.555 Z"/>
- <path style="opacity:0.41;fill:#6AB3EA;enable-background:new ;" d="M 458.404 160.434 C 449.674 160.434 441.45 162.579 434.209 166.352 C 427.002 152.079 414.944 140.68 400.186 134.337 C 400.186 134.206 400.196 134.079 400.196 133.948 C 400.196 61.395 341.38 2.58 268.827 2.58 C 257.171 2.58 245.875 4.105 235.117 6.955 C 291.333 21.84 332.772 73.052 332.772 133.95 C 332.772 134.081 332.763 134.208 332.762 134.339 C 347.519 140.681 359.578 152.081 366.785 166.354 C 374.026 162.58 382.25 160.436 390.98 160.436 C 419.943 160.436 443.422 183.914 443.422 212.878 C 443.422 241.841 419.944 265.32 390.98 265.32 L 458.404 265.32 C 487.367 265.32 510.846 241.841 510.846 212.878 C 510.846 183.912 487.367 160.434 458.404 160.434 Z"/>
- <g style="opacity:0.41;">
- <path style="fill:#6AB3EA;" d="M258.252,34.812c0,3.364-2.216,6.456-5.612,7.421c-40.109,11.389-68.121,48.482-68.121,90.201 c0,4.264-3.455,7.718-7.718,7.718s-7.718-3.455-7.718-7.718c0-48.587,32.626-91.785,79.341-105.052 c4.1-1.165,8.369,1.216,9.534,5.316C258.157,33.404,258.252,34.114,258.252,34.812z"/>
- </g>
- </g>
-</svg>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
- <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
- <path fill="#F8EFE0" d="M 11.018 52.475 L 11.018 31.819 C 7.317 33.065 4.779 29.687 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 51.937 51.358 C 43.944 54.785 42.3 46.755 42.28 46.918 C 41.461 53.613 28.847 53.227 26.809 48.767 C 26.439 47.958 26.67 47.804 26.141 47.766 C 23.045 47.544 22.868 55.347 11.018 52.475 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
- <path fill="#D93133" d="M 11.018 31.819 C 10.054 32.144 9.151 32.151 8.401 31.927 C 7.816 31.754 7.322 31.444 6.959 31.043 C 6.596 30.643 6.366 30.156 6.295 29.618 C 6.188 28.785 6.472 27.843 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 49.63 30.982 C 49.63 30.618 33.464 19.43 31.679 18.213 C 29.788 19.473 13.326 30.571 13.326 31.04 L 11.018 31.819 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
- <path fill="#313A58" d="M 31.595 25.496 C 33.228 25.496 34.711 26.081 35.784 27.021 C 36.861 27.963 37.526 29.076 37.526 30.503 L 37.526 35.325 L 25.662 35.325 L 25.662 30.503 C 25.662 29.073 26.33 27.961 27.404 27.021 C 28.479 26.081 29.963 25.496 31.595 25.496 Z" style=""/>
- <path fill="#ABB9BC" d="M 32.111 31.421 L 32.111 34.426 L 36.496 34.426 L 36.496 31.421 L 32.111 31.421 Z M 32.111 26.424 L 32.111 30.517 L 36.496 30.517 L 36.496 30.505 C 36.496 29.326 35.945 28.439 35.056 27.661 C 34.282 26.983 33.252 26.529 32.111 26.424 Z M 31.079 30.517 L 31.079 26.424 C 29.936 26.531 28.909 26.983 28.134 27.661 C 27.245 28.439 26.694 29.326 26.694 30.505 L 26.694 30.517 L 31.079 30.517 Z M 31.079 34.423 L 31.079 31.421 L 26.694 31.421 L 26.694 34.426 L 31.079 34.426 L 31.079 34.423 Z" style=""/>
- <path fill="#313A58" d="M 51.92 31.732 L 49.64 30.959 L 49.64 52.389 L 51.92 52.389 L 51.92 31.732 Z M 10.908 31.819 L 13.189 31.046 L 13.189 52.476 L 10.908 52.476 L 10.908 31.819 Z" style=""/>
- <path d="M 11.097 51.603 C 13.269 52.586 15.988 52.276 18.451 51.315 C 21.367 50.176 23.866 48.168 24.668 46.318 C 24.9 45.781 25.509 45.54 26.029 45.779 C 26.259 45.885 26.444 46.075 26.547 46.312 C 27.432 48.152 28.886 49.487 30.554 50.246 C 31.623 50.733 32.775 50.983 33.918 50.978 C 35.051 50.973 36.18 50.717 37.211 50.195 C 38.688 49.446 39.974 48.13 40.802 46.195 C 41.031 45.656 41.641 45.412 42.163 45.649 C 42.416 45.764 42.614 45.978 42.711 46.245 C 43.106 47.121 43.54 47.869 44.009 48.496 C 45.11 49.969 46.402 50.756 47.805 50.981 C 49.259 51.215 50.874 50.868 52.56 50.07 C 53.763 49.501 55 48.701 56.239 47.714 L 57.499 49.397 C 56.142 50.478 54.77 51.363 53.416 52.004 C 51.373 52.971 49.365 53.383 47.49 53.082 C 45.567 52.773 43.824 51.731 42.377 49.796 C 42.148 49.488 41.933 49.17 41.734 48.842 C 40.756 50.32 39.505 51.399 38.116 52.103 C 36.799 52.772 35.361 53.098 33.918 53.104 C 32.484 53.109 31.046 52.799 29.722 52.197 C 28.122 51.468 26.677 50.311 25.588 48.764 C 24.183 50.57 21.811 52.279 19.178 53.307 C 16.265 54.444 12.989 54.782 10.273 53.553 L 11.097 51.603 Z" style="fill: rgb(30, 130, 255);"/>
- <path d="M 8.218 34.7 C 8.218 34.7 8.173 34.7 8.13 34.7 C 8.041 34.7 7.997 34.7 7.953 34.64 L 7.908 34.64 C 6.888 34.399 6.046 33.017 5.958 31.515 L 5.958 31.034 C 6.003 30.794 6.046 30.494 6.091 30.192 C 6.18 30.013 6.268 29.772 6.357 29.532 L 6.667 28.93 C 7.376 27.789 7.953 26.648 8.351 25.445 C 8.794 26.888 9.504 28.15 10.08 29.111 C 10.124 29.231 10.213 29.411 10.346 29.592 C 10.434 29.832 10.567 30.133 10.701 30.373 C 10.745 30.553 10.789 30.854 10.834 31.094 L 10.834 31.455 C 10.834 31.515 10.834 31.575 10.834 31.635 C 10.834 31.635 10.834 31.695 10.834 31.695 L 10.834 31.756 L 10.834 31.815 C 10.701 33.138 9.903 34.399 8.928 34.64 L 8.883 34.64 C 8.839 34.64 8.794 34.7 8.706 34.7 C 8.661 34.7 8.618 34.7 8.618 34.7 L 8.218 34.7" fill="#1e82ff" style=""/>
- <path d="M 17.152 21.924 C 17.152 21.924 17.107 21.924 17.064 21.924 C 16.975 21.924 16.931 21.924 16.887 21.864 L 16.842 21.864 C 15.822 21.623 14.98 20.241 14.892 18.739 L 14.892 18.258 C 14.937 18.018 14.98 17.718 15.025 17.416 C 15.114 17.237 15.202 16.996 15.291 16.756 L 15.601 16.154 C 16.31 15.013 16.887 13.872 17.285 12.669 C 17.728 14.112 18.438 15.374 19.014 16.335 C 19.058 16.455 19.147 16.635 19.28 16.816 C 19.368 17.056 19.501 17.357 19.635 17.597 C 19.679 17.777 19.723 18.078 19.768 18.318 L 19.768 18.679 C 19.768 18.739 19.768 18.799 19.768 18.859 C 19.768 18.859 19.768 18.919 19.768 18.919 L 19.768 18.98 L 19.768 19.039 C 19.635 20.362 18.837 21.623 17.862 21.864 L 17.817 21.864 C 17.773 21.864 17.728 21.924 17.64 21.924 C 17.595 21.924 17.552 21.924 17.552 21.924 L 17.152 21.924" fill="#1e82ff" style=""/>
- <path d="M 42.51 27.949 C 42.51 27.949 42.465 27.949 42.422 27.949 C 42.333 27.949 42.289 27.949 42.245 27.889 L 42.2 27.889 C 41.18 27.648 40.338 26.266 40.25 24.764 L 40.25 24.283 C 40.295 24.043 40.338 23.743 40.383 23.441 C 40.472 23.262 40.56 23.021 40.649 22.781 L 40.959 22.179 C 41.668 21.038 42.245 19.897 42.643 18.694 C 43.086 20.137 43.796 21.399 44.372 22.36 C 44.416 22.48 44.505 22.66 44.638 22.841 C 44.726 23.081 44.859 23.382 44.993 23.622 C 45.037 23.802 45.081 24.103 45.126 24.343 L 45.126 24.704 C 45.126 24.764 45.126 24.824 45.126 24.884 C 45.126 24.884 45.126 24.944 45.126 24.944 L 45.126 25.005 L 45.126 25.064 C 44.993 26.387 44.195 27.648 43.22 27.889 L 43.175 27.889 C 43.131 27.889 43.086 27.949 42.998 27.949 C 42.953 27.949 42.91 27.949 42.91 27.949 L 42.51 27.949" fill="#1e82ff" style=""/>
- <path d="M 30.168 12.518 C 30.168 12.518 30.123 12.518 30.08 12.518 C 29.991 12.518 29.947 12.518 29.903 12.458 L 29.858 12.458 C 28.838 12.217 27.996 10.835 27.908 9.333 L 27.908 8.852 C 27.953 8.612 27.996 8.312 28.041 8.01 C 28.13 7.831 28.218 7.59 28.307 7.35 L 28.617 6.748 C 29.326 5.607 29.903 4.466 30.301 3.263 C 30.744 4.706 31.454 5.968 32.03 6.929 C 32.074 7.049 32.163 7.229 32.296 7.41 C 32.384 7.65 32.517 7.951 32.651 8.191 C 32.695 8.371 32.739 8.672 32.784 8.912 L 32.784 9.273 C 32.784 9.333 32.784 9.393 32.784 9.453 C 32.784 9.453 32.784 9.513 32.784 9.513 L 32.784 9.574 L 32.784 9.633 C 32.651 10.956 31.853 12.217 30.878 12.458 L 30.833 12.458 C 30.789 12.458 30.744 12.518 30.656 12.518 C 30.611 12.518 30.568 12.518 30.568 12.518 L 30.168 12.518" fill="#1e82ff" style=""/>
- <path d="M 54.328 36.78 C 54.328 36.78 54.283 36.78 54.24 36.78 C 54.151 36.78 54.107 36.78 54.063 36.72 L 54.018 36.72 C 52.998 36.479 52.156 35.097 52.068 33.595 L 52.068 33.114 C 52.113 32.874 52.156 32.574 52.201 32.272 C 52.29 32.093 52.378 31.852 52.467 31.612 L 52.777 31.01 C 53.486 29.869 54.063 28.728 54.461 27.525 C 54.904 28.968 55.614 30.23 56.19 31.191 C 56.234 31.311 56.323 31.491 56.456 31.672 C 56.544 31.912 56.677 32.213 56.811 32.453 C 56.855 32.633 56.899 32.934 56.944 33.174 L 56.944 33.535 C 56.944 33.595 56.944 33.655 56.944 33.715 C 56.944 33.715 56.944 33.775 56.944 33.775 L 56.944 33.836 L 56.944 33.895 C 56.811 35.218 56.013 36.479 55.038 36.72 L 54.993 36.72 C 54.949 36.72 54.904 36.78 54.816 36.78 C 54.771 36.78 54.728 36.78 54.728 36.78 L 54.328 36.78" fill="#1e82ff" style=""/>
- <path d="M 10.92 57.018 C 13.092 58.001 15.811 57.691 18.274 56.73 C 21.19 55.591 23.689 53.583 24.491 51.733 C 24.723 51.196 25.332 50.955 25.852 51.194 C 26.082 51.3 26.267 51.49 26.37 51.727 C 27.255 53.567 28.709 54.902 30.377 55.661 C 31.446 56.148 32.598 56.398 33.741 56.393 C 34.874 56.388 36.003 56.132 37.034 55.61 C 38.511 54.861 39.797 53.545 40.625 51.61 C 40.854 51.071 41.464 50.827 41.986 51.064 C 42.239 51.179 42.437 51.393 42.534 51.66 C 42.929 52.536 43.363 53.284 43.832 53.911 C 44.933 55.384 46.225 56.171 47.628 56.396 C 49.082 56.63 50.697 56.283 52.383 55.485 C 53.586 54.916 54.823 54.116 56.062 53.129 L 57.322 54.812 C 55.965 55.893 54.593 56.778 53.239 57.419 C 51.196 58.386 49.188 58.798 47.313 58.497 C 45.39 58.188 43.647 57.146 42.2 55.211 C 41.971 54.903 41.756 54.585 41.557 54.257 C 40.579 55.735 39.328 56.814 37.939 57.518 C 36.622 58.187 35.184 58.513 33.741 58.519 C 32.307 58.524 30.869 58.214 29.545 57.612 C 27.945 56.883 26.5 55.726 25.411 54.179 C 24.006 55.985 21.634 57.694 19.001 58.722 C 16.088 59.859 12.812 60.197 10.096 58.968 L 10.92 57.018 Z" style="fill: rgb(30, 130, 255);"/>
-</svg>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
- <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
- <path d="M 10.382 37.307 C 12.554 38.29 15.273 37.98 17.736 37.019 C 20.652 35.88 23.151 33.872 23.953 32.022 C 24.185 31.485 24.794 31.244 25.314 31.483 C 25.544 31.589 25.729 31.779 25.832 32.016 C 26.717 33.856 28.171 35.191 29.839 35.95 C 30.908 36.437 32.06 36.687 33.203 36.682 C 34.336 36.677 35.465 36.421 36.496 35.899 C 37.973 35.15 39.259 33.834 40.087 31.899 C 40.316 31.36 40.926 31.116 41.448 31.353 C 41.701 31.468 41.899 31.682 41.996 31.949 C 42.391 32.825 42.825 33.573 43.294 34.2 C 44.395 35.673 45.687 36.46 47.09 36.685 C 48.544 36.919 50.159 36.572 51.845 35.774 C 53.048 35.205 54.285 34.405 55.524 33.418 L 56.784 35.101 C 55.427 36.182 54.055 37.067 52.701 37.708 C 50.658 38.675 48.65 39.087 46.775 38.786 C 44.852 38.477 43.109 37.435 41.662 35.5 C 41.433 35.192 41.218 34.874 41.019 34.546 C 40.041 36.024 38.79 37.103 37.401 37.807 C 36.084 38.476 34.646 38.802 33.203 38.808 C 31.769 38.813 30.331 38.503 29.007 37.901 C 27.407 37.172 25.962 36.015 24.873 34.468 C 23.468 36.274 21.096 37.983 18.463 39.011 C 15.55 40.148 12.274 40.486 9.558 39.257 L 10.382 37.307 Z" style="fill: rgb(30, 130, 255);"/>
- <path d="M 10.205 42.722 C 12.377 43.705 15.096 43.395 17.559 42.434 C 20.475 41.295 22.974 39.287 23.776 37.437 C 24.008 36.9 24.617 36.659 25.137 36.898 C 25.367 37.004 25.552 37.194 25.655 37.431 C 26.54 39.271 27.994 40.606 29.662 41.365 C 30.731 41.852 31.883 42.102 33.026 42.097 C 34.159 42.092 35.288 41.836 36.319 41.314 C 37.796 40.565 39.082 39.249 39.91 37.314 C 40.139 36.775 40.749 36.531 41.271 36.768 C 41.524 36.883 41.722 37.097 41.819 37.364 C 42.214 38.24 42.648 38.988 43.117 39.615 C 44.218 41.088 45.51 41.875 46.913 42.1 C 48.367 42.334 49.982 41.987 51.668 41.189 C 52.871 40.62 54.108 39.82 55.347 38.833 L 56.607 40.516 C 55.25 41.597 53.878 42.482 52.524 43.123 C 50.481 44.09 48.473 44.502 46.598 44.201 C 44.675 43.892 42.932 42.85 41.485 40.915 C 41.256 40.607 41.041 40.289 40.842 39.961 C 39.864 41.439 38.613 42.518 37.224 43.222 C 35.907 43.891 34.469 44.217 33.026 44.223 C 31.592 44.228 30.154 43.918 28.83 43.316 C 27.23 42.587 25.785 41.43 24.696 39.883 C 23.291 41.689 20.919 43.398 18.286 44.426 C 15.373 45.563 12.097 45.901 9.381 44.672 L 10.205 42.722 Z" style="fill: rgb(30, 130, 255);"/>
- <path d="M 32.307 33.157 C 30.008 33.038 27.346 31.638 25.776 29.76 C 25.48 29.421 25.206 29.064 24.956 28.688 C 23.585 30.561 21.153 32.357 18.438 33.424 C 15.546 34.563 12.297 34.903 9.61 33.677 L 10.301 32.03 C 12.342 32.962 14.845 32.775 17.183 31.979 C 17.253 28.669 18.202 25.534 19.838 22.875 C 21.336 20.442 23.646 18.223 26.281 16.786 C 29.429 15.07 33.861 14.165 36.905 16.582 C 40.064 19.088 39.596 23.333 36.462 25.669 C 35.744 26.203 34.894 26.543 34.027 26.631 C 33.319 26.702 32.602 26.606 31.934 26.309 C 31.263 26.011 30.648 25.518 30.154 24.801 C 29.581 23.968 29.17 22.827 29.031 21.336 C 28.992 20.904 29.296 20.523 29.711 20.48 C 30.125 20.44 30.493 20.757 30.532 21.188 C 30.643 22.376 30.953 23.26 31.383 23.885 C 31.708 24.357 32.102 24.676 32.525 24.866 C 32.954 25.056 33.42 25.116 33.885 25.069 C 34.48 25.009 35.072 24.769 35.582 24.39 C 37.883 22.674 38.346 19.7 35.99 17.83 C 26.886 12.683 22.711 27.316 31.469 31.199 C 32.079 31.342 32.703 31.412 33.329 31.411 C 34.495 31.407 35.656 31.142 36.717 30.6 C 38.239 29.821 39.562 28.459 40.413 26.455 C 40.605 26 41.116 25.793 41.554 25.994 C 41.766 26.091 41.931 26.272 42.013 26.498 C 42.418 27.404 42.863 28.177 43.343 28.823 C 44.48 30.357 45.818 31.177 47.274 31.413 C 48.771 31.655 50.429 31.298 52.154 30.475 C 53.379 29.893 54.635 29.073 55.89 28.065 L 56.947 29.488 C 55.592 30.576 54.222 31.465 52.872 32.109 C 50.847 33.075 48.86 33.487 47.01 33.188 C 45.117 32.881 43.402 31.847 41.976 29.924 C 41.694 29.542 41.434 29.145 41.197 28.733 C 40.211 30.324 38.919 31.474 37.476 32.212 C 36.175 32.876 34.753 33.201 33.329 33.207 C 32.988 33.209 32.647 33.192 32.307 33.157 Z" style="fill: rgb(30, 130, 255);"/>
-</svg>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
- <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
- <path
- d="m61.55 22.14c-3.06-.84-7.3-2.16-9.33-3.51-3.39-2.25-4.77-2.26-7.12-3.02-2.35-.76-4.78-2.08-4.78-2.08s-2.57-2.17-6.5-2.77c-3.92-.6-5.65-2.61-5.65-2.61s-.6-1.38-2.2-1.96c-2.54-1.01-6.25 2.29-8.28 7.38-2.03 5.09-1.61 10.04.94 11.05 0 0 6.32 2.52 10.66 2.08 4.34-.44 7.8.39 7.8.39s3.64.85 7.37.58c3.72-.27 6.09.62 6.09.62s2.41.67 10.18.27c.31-.43.57-.91.77-1.43.67-1.69.64-3.47.05-4.99z"
- fill="#db5336" stroke="#db5336" stroke-miterlimit="10" />
- <ellipse transform="matrix(-.929-.37.37-.929 37.3113 37.9507)" cx="22.3" cy="15.4" rx="4.96" ry="9.92"
- fill="#ca2a14" />
- <g fill="#fff">
- <path
- d="m61.55 22.14c-1.77-.48-3.92-1.13-5.82-1.84.77 1.74.88 3.69.16 5.5-.46 1.15-1.2 2.1-2.12 2.84 1.58.07 3.84.09 6.97-.07.31-.43.57-.91.77-1.43.66-1.7.63-3.48.04-5" />
- <path
- d="m50.1 17.36c-1.98-1.03-3.21-1.17-5-1.75-.5-.16-1.01-.35-1.49-.54 1.27 2.47 1.49 5.53.35 8.41-.67 1.68-1.73 3.09-3.01 4.15 1.08.08 2.29.12 3.51.03 1.07-.08 2.02-.06 2.84.01 1.21-.93 2.19-2.2 2.8-3.73.89-2.21.82-4.56 0-6.58" />
- <path
- d="m37.81 12c-1.06-.5-2.42-1-3.99-1.24-.84-.13-1.57-.32-2.22-.54 1.6 2.52 1.73 6.77.05 10.99-.89 2.24-2.16 4.14-3.59 5.53.42 0 .83-.01 1.23-.05 1.8-.18 3.45-.15 4.76-.04 1.75-1.09 3.32-2.98 4.29-5.4 1.4-3.53 1.1-7.14-.53-9.25" />
- <path
- d="m24.53 15.02c-1.09 2.73-1.32 5.44-.8 7.43 1.21-1.31 2.34-3.11 3.18-5.22 1.08-2.72 1.47-5.4 1.2-7.46-1.4 1.19-2.7 3.02-3.58 5.25" />
- </g>
- <g fill="none" stroke="#1a171b" stroke-miterlimit="10">
- <path d="m13.55 10.5 4.7 2.19" />
- <path d="m13.55 10.5 13.28-3.87" />
- <path d="m13.55 10.5 8.74 13.45" />
- <path d="M 13.55,10.5 7,9" />
- </g>
- <path d="M4.5,59.5V9c0-1.38,1.12-2.5,2.5-2.5S9.5,7.62,9.5,9c0,1.21-0.86,2.22-2,2.45V59.5H4.5z" fill="#8b96ac" />
- <path
- d="m7 7c1.1 0 2 0.9 2 2s-0.9 2-2 2v48h-2v-50c0-1.1 0.9-2 2-2m0-1c-1.65 0-3 1.35-3 3v51h4v-48.17c1.16-0.41 2-1.52 2-2.83 0-1.65-1.35-3-3-3z"
- fill="#676b72" />
-</svg>
\ No newline at end of file
--- /dev/null
+This content is produced and maintained by the openHAB project.
+
+* Project home: https://www.openhab.org
+
+== Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Public License 2.0 which is available at
+https://www.eclipse.org/legal/epl-2.0/.
+
+== Source Code
+
+https://github.com/openhab/openhab-addons
--- /dev/null
+# Meteo France Binding
+
+This binding provides information made available by Meteo France:
+
+* Alert level regarding major weather related risk factors (`vigilance` Thing)
+* Rain intensity forecasts (`rain-forecast`Thing)
+
+This binding provides its own icon set and provides appropriate static and dynamic SVG icons (see items examples below).
+
+## Discovery
+
+Once a bridge with the API key has been created, appropriate departments can be auto discovered based on system location.
+
+## Binding Configuration
+
+The binding has no configuration options, all configuration is done at Bridge and Thing level.
+
+## Bridge Configuration
+
+The `api` bridge has only one configuration parameter :
+
+| Parameter | Description |
+|-----------|-------------------------------------------------------|
+| apikey | Data-platform token to access the service. Mandatory. |
+
+To obtain an API key, you must create an account on https://portail-api.meteofrance.fr/web/fr/
+Inside the API Portal, create an application on "Bulletin Vigilance" and generate they API key (set duration to 0).
+
+## Thing Configuration
+
+The `vigilance` thing has these configuration parameters:
+
+| Parameter | Description |
+|------------|-------------------------------------------------------------------------|
+| department | Code of the department (two digits). |
+| refresh | Refresh interval in minutes. Optional, the default value is 60 minutes. |
+
+The `rain-forecast` thing has this configuration parameters:
+
+| Parameter | Description |
+|-----------|--------------------------------------------------------------|
+| location | Geo coordinates to be considered by the service. |
+
+## Channels
+
+The information that are retrieved is available as these channels:
+
+| Channel ID | Item Type | Description |
+|-----------------------|-----------|-----------------------------------------------|
+| observation-time | DateTime | Date and time of report validity start |
+| end-time | DateTime | Date and time of report validity end |
+| comment | String | General comments on alerts for the department |
+| vent | Number | Wind alert level (*) |
+| pluie-inondation | Number | Rain alert level (*) |
+| orage | Number | Storm alert level (*) |
+| inondation | Number | Flood alert level (*) |
+| neige | Number | Snow alert level (*) |
+| canicule | Number | Heat alert level (*) |
+| grand-froid | Number | Cold alert level (*) |
+| avalanches | Number | Avalanche alert level (*) |
+| vague-submersion | Number | Wave submersion alert level (*) |
+| pluie-inondation-icon | Image | Pictogram of the Rain alert level |
+| vent-icon | Image | Pictogram of the Wind alert level |
+| orage-icon | Image | Pictogram of Storm alert level |
+| inondation-icon | Image | Pictogram of Flood alert level |
+| neige-icon | Image | Pictogram of Snow alert level |
+| canicule-icon | Image | Pictogram of Heat alert level |
+| grand-froid-icon | Image | Pictogram of Cold alert level |
+| avalanches-icon | Image | Pictogram of Avalanche alert level |
+| vague-submersion-icon | Image | Pictogram of Wave Submersion alert level |
+
+(*) Each alert level has an associated color and description:
+
+| Code | Color | Description |
+|------|--------|-------------------------------------------|
+| 0 | Green | No particular vigilance |
+| 1 | Yellow | Be attentive to the weather situation |
+| 2 | Orange | Be "very vigilant" in the concerned areas |
+| 3 | Red | Absolute vigilance required |
+
+## Provided icon set
+
+This binding has its own IconProvider and makes available the following list of icons
+
+| Icon Name | Dynamic | Illustration |
+|---------------------------------|---------|--------------|
+| oh:meteofrance:vent | Yes |  |
+| oh:meteofrance:pluie-inondation | Yes |  |
+| oh:meteofrance:orage | Yes |  |
+| oh:meteofrance:inondation | Yes |  |
+| oh:meteofrance:neige | Yes |  |
+| oh:meteofrance:canicule | Yes |  |
+| oh:meteofrance:grand-froid | Yes |  |
+| oh:meteofrance:avalanches | Yes |  |
+| oh:meteofrance:vague-submersion | Yes |  |
+| oh:meteofrance:meteo_france | No |  |
+| oh:meteofrance:intensity | Yes |  |
+
+## Full Example
+
+meteoalert.things:
+
+```java
+Thing meteofrance:department:yvelines @ "MyCity" [department="78", refresh=12]
+```
+
+meteoalert.items:
+
+```java
+Group gMeteoAlert "Alertes Météo" <oh:meteofrance:meteo_france>
+String MA_Dept78 "Département 78 [%s]" <text> (gMeteoAlert) {channel="meteofrance:department:yvelines:comment"}
+Number MA_etat_canicule "Canicule [%s]" <oh:meteofrance:canicule> (gMeteoAlert) {channel="meteofrance:department:yvelines:canicule"}
+Number MA_etat_grand_froid "Grand Froid [%s]" <oh:meteofrance:grand-froid> (gMeteoAlert) {channel="meteofrance:department:yvelines:grand-froid"}
+Number MA_etat_pluie_inondation "Pluie-Inondation [%s]" <oh:meteofrance:pluie-inondation> (gMeteoAlert) {channel="meteofrance:department:yvelines:pluie-inondation"}
+Number MA_etat_neige "Neige [%s]" <oh:meteofrance:neige> (gMeteoAlert) {channel="meteofrance:department:yvelines:neige"}
+Number MA_etat_vent "Vent [%s]" <oh:meteofrance:vent> (gMeteoAlert) {channel="meteofrance:department:yvelines:vent"}
+Number MA_etat_inondation "Inondation [%s]" <oh:meteofrance:inondation> (gMeteoAlert) {channel="meteofrance:department:yvelines:inondation"}
+Number MA_etat_orage "Orage [%s]" <oh:meteofrance:orage> (gMeteoAlert) {channel="meteofrance:department:yvelines:orage"}
+Number MA_etat_avalanche "Avalanches [%s]" <oh:meteofrance:avalanches> (gMeteoAlert) {channel="meteofrance:department:yvelines:avalanches"}
+
+Image MA_icon_canicule "Canicule" <oh:meteofrance:canicule> (gMeteoAlert) {channel="meteofrance:department:yvelines:canicule-icon"}
+Image MA_icon_grand_froid "Grand Froid" <oh:meteofrance:grand-froid> (gMeteoAlert) {channel="meteofrance:department:yvelines:grand-froid-icon"}
+Image MA_icon_pluie_inondation "Pluie-Inondation" <oh:meteofrance:pluie-inondation> (gMeteoAlert) {channel="meteofrance:department:yvelines:pluie-inondation-icon"}
+Image MA_icon_neige "Neige" <oh:meteofrance:neige> (gMeteoAlert) {channel="meteofrance:department:yvelines:neige-icon"}
+Image MA_icon_vent "Vent" <oh:meteofrance:vent> (gMeteoAlert) {channel="meteofrance:department:yvelines:vent-icon"}
+Image MA_icon_inondation "Inondation" <oh:meteofrance:inondation> (gMeteoAlert) {channel="meteofrance:department:yvelines:inondation-icon"}
+Image MA_icon_orage "Orage" <oh:meteofrance:orage> (gMeteoAlert) {channel="meteofrance:department:yvelines:orage-icon"}
+Image MA_icon_avalanche "Avalanche" <oh:meteofrance:avalanches> (gMeteoAlert) {channel="meteofrance:department:yvelines:avalanches-icon"}
+
+DateTime MA_ObservationTS "Timestamp [%1$tH:%1$tM]" <time> (gMeteoAlert) {channel="meteofrance:department:yvelines:observation-time"}
+
+```
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <g transform="matrix(0.095654, 0, 0, 0.103801, 7.65905, -0.7645)" style="">
+ <g>
+ <path style="fill:#9B5C5C;" d="M277.259,58.637c-11.695-20.344-30.835-20.344-42.53,0L4.978,432.587 c-11.695,20.342-2.07,36.966,21.398,36.966h459.235c23.468,0,33.093-16.624,21.405-36.966L277.259,58.637z"/>
+ <path style="fill:#9B5C5C;" d="M277.259,57.683c-11.695-20.328-30.835-20.328-42.53,0l-23.538,59.732l-32.538,31.78L4.978,432.587 c-11.695,20.342-2.07,36.966,21.398,36.966h459.235c23.468,0,33.093-16.624,21.405-36.966l-56.124-91.592l-84.06-104.052 L277.259,57.683z"/>
+ </g>
+ <g>
+ <path style="fill:#CBD0D8;" d="M426.629,226.272c-23.562,0-42.671,19.108-42.671,42.671c0,23.554,19.109,42.646,42.671,42.646 c23.545,0,42.654-19.093,42.654-42.646C469.283,245.381,450.174,226.272,426.629,226.272L426.629,226.272z"/>
+ <path style="fill:#CBD0D8;" d="M394.63,226.272c0,5.89-4.766,10.671-10.672,10.671c-5.875,0-10.656-4.781-10.656-10.671 c0-5.875,4.781-10.656,10.656-10.656C389.864,215.616,394.63,220.397,394.63,226.272z"/>
+ <path style="fill:#CBD0D8;" d="M426.629,204.944c0,5.891-4.781,10.672-10.671,10.672c-5.891,0-10.656-4.781-10.656-10.672 s4.766-10.655,10.656-10.655C421.848,194.289,426.629,199.054,426.629,204.944z"/>
+ <path style="fill:#CBD0D8;" d="M383.958,183.617c0,5.891-4.766,10.672-10.656,10.672s-10.656-4.781-10.656-10.672 s4.766-10.656,10.656-10.656S383.958,177.726,383.958,183.617z"/>
+ <path style="fill:#CBD0D8;" d="M351.974,151.634c0,5.891-4.766,10.655-10.672,10.655c-5.874,0-10.655-4.765-10.655-10.655 s4.781-10.671,10.655-10.671C347.209,140.963,351.974,145.744,351.974,151.634z"/>
+ </g>
+ <path style="fill:#E6E9ED;" d="M 273.368 152.384 C 274.649 151.868 275.993 151.634 277.321 151.634 C 280.992 151.634 284.554 153.54 286.523 156.884 C 286.523 156.884 355.865 257.194 381.786 300.341 C 407.708 343.495 450.892 341.027 450.892 341.027 L 277.259 57.683 C 265.564 37.355 246.424 37.355 234.729 57.683 L 178.653 149.196 C 178.653 149.196 210.879 171.539 225.503 171.539 C 240.126 171.539 273.368 152.384 273.368 152.384 Z"/>
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
+ <g fill="#dae1e4">
+ <circle cx="32" cy="55" r="9" />
+ <circle cx="32" cy="6" r="6" />
+ </g>
+ <circle cx="32" cy="6" r="5" fill="#d20014" />
+ <path d="m26 6h12v50h-12z" fill="#dae1e4" />
+ <g fill="#d20014">
+ <path d="m27 6h10v48.94h-10z" />
+ <circle cx="32" cy="55" r="8" />
+ </g>
+ <g fill="#fff">
+ <path d="m33 9h5v2h-5z" />
+ <path d="m33 17h5v2h-5z" />
+ <path d="m33 25h5v2h-5z" />
+ <path d="m33 33h5v2h-5z" />
+ <path d="m33 41h5v2h-5z" />
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
+ <circle cx="32" cy="6" r="6" fill="#dae1e4" />
+ <circle cx="32" cy="6" r="5" fill="#c4cacc" />
+ <path d="m26 6h12v50h-12z" fill="#dae1e4" />
+ <path d="m27 6h10v48.94h-10z" fill="#c4cacc" />
+ <circle cx="32" cy="55" r="9" fill="#dae1e4" />
+ <g fill="#2e7de5">
+ <circle cx="32" cy="55" r="8" />
+ <path d="m27 39h10v12h-10z" />
+ </g>
+ <g fill="#fff">
+ <path d="m33 9h5v2h-5z" />
+ <path d="m33 17h5v2h-5z" />
+ <path d="m33 25h5v2h-5z" />
+ <path d="m33 33h5v2h-5z" />
+ <path d="m33 41h5v2h-5z" />
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <path fill="#F8EFE0" d="M 11.018 52.475 L 11.018 31.819 C 7.317 33.065 4.779 29.687 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 51.937 51.358 C 43.944 54.785 42.3 46.755 42.28 46.918 C 41.461 53.613 28.847 53.227 26.809 48.767 C 26.439 47.958 26.67 47.804 26.141 47.766 C 23.045 47.544 22.868 55.347 11.018 52.475 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
+ <path fill="#D93133" d="M 11.018 31.819 C 10.054 32.144 9.151 32.151 8.401 31.927 C 7.816 31.754 7.322 31.444 6.959 31.043 C 6.596 30.643 6.366 30.156 6.295 29.618 C 6.188 28.785 6.472 27.843 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 49.63 30.982 C 49.63 30.618 33.464 19.43 31.679 18.213 C 29.788 19.473 13.326 30.571 13.326 31.04 L 11.018 31.819 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
+ <path fill="#313A58" d="M 31.595 25.496 C 33.228 25.496 34.711 26.081 35.784 27.021 C 36.861 27.963 37.526 29.076 37.526 30.503 L 37.526 35.325 L 25.662 35.325 L 25.662 30.503 C 25.662 29.073 26.33 27.961 27.404 27.021 C 28.479 26.081 29.963 25.496 31.595 25.496 Z" style=""/>
+ <path fill="#ABB9BC" d="M 32.111 31.421 L 32.111 34.426 L 36.496 34.426 L 36.496 31.421 L 32.111 31.421 Z M 32.111 26.424 L 32.111 30.517 L 36.496 30.517 L 36.496 30.505 C 36.496 29.326 35.945 28.439 35.056 27.661 C 34.282 26.983 33.252 26.529 32.111 26.424 Z M 31.079 30.517 L 31.079 26.424 C 29.936 26.531 28.909 26.983 28.134 27.661 C 27.245 28.439 26.694 29.326 26.694 30.505 L 26.694 30.517 L 31.079 30.517 Z M 31.079 34.423 L 31.079 31.421 L 26.694 31.421 L 26.694 34.426 L 31.079 34.426 L 31.079 34.423 Z" style=""/>
+ <path fill="#313A58" d="M 51.92 31.732 L 49.64 30.959 L 49.64 52.389 L 51.92 52.389 L 51.92 31.732 Z M 10.908 31.819 L 13.189 31.046 L 13.189 52.476 L 10.908 52.476 L 10.908 31.819 Z" style=""/>
+ <path d="M 11.097 51.603 C 13.269 52.586 15.988 52.276 18.451 51.315 C 21.367 50.176 23.866 48.168 24.668 46.318 C 24.9 45.781 25.509 45.54 26.029 45.779 C 26.259 45.885 26.444 46.075 26.547 46.312 C 27.432 48.152 28.886 49.487 30.554 50.246 C 31.623 50.733 32.775 50.983 33.918 50.978 C 35.051 50.973 36.18 50.717 37.211 50.195 C 38.688 49.446 39.974 48.13 40.802 46.195 C 41.031 45.656 41.641 45.412 42.163 45.649 C 42.416 45.764 42.614 45.978 42.711 46.245 C 43.106 47.121 43.54 47.869 44.009 48.496 C 45.11 49.969 46.402 50.756 47.805 50.981 C 49.259 51.215 50.874 50.868 52.56 50.07 C 53.763 49.501 55 48.701 56.239 47.714 L 57.499 49.397 C 56.142 50.478 54.77 51.363 53.416 52.004 C 51.373 52.971 49.365 53.383 47.49 53.082 C 45.567 52.773 43.824 51.731 42.377 49.796 C 42.148 49.488 41.933 49.17 41.734 48.842 C 40.756 50.32 39.505 51.399 38.116 52.103 C 36.799 52.772 35.361 53.098 33.918 53.104 C 32.484 53.109 31.046 52.799 29.722 52.197 C 28.122 51.468 26.677 50.311 25.588 48.764 C 24.183 50.57 21.811 52.279 19.178 53.307 C 16.265 54.444 12.989 54.782 10.273 53.553 L 11.097 51.603 Z" style="fill: rgb(30, 130, 255);"/>
+ <path d="M 10.92 57.018 C 13.092 58.001 15.811 57.691 18.274 56.73 C 21.19 55.591 23.689 53.583 24.491 51.733 C 24.723 51.196 25.332 50.955 25.852 51.194 C 26.082 51.3 26.267 51.49 26.37 51.727 C 27.255 53.567 28.709 54.902 30.377 55.661 C 31.446 56.148 32.598 56.398 33.741 56.393 C 34.874 56.388 36.003 56.132 37.034 55.61 C 38.511 54.861 39.797 53.545 40.625 51.61 C 40.854 51.071 41.464 50.827 41.986 51.064 C 42.239 51.179 42.437 51.393 42.534 51.66 C 42.929 52.536 43.363 53.284 43.832 53.911 C 44.933 55.384 46.225 56.171 47.628 56.396 C 49.082 56.63 50.697 56.283 52.383 55.485 C 53.586 54.916 54.823 54.116 56.062 53.129 L 57.322 54.812 C 55.965 55.893 54.593 56.778 53.239 57.419 C 51.196 58.386 49.188 58.798 47.313 58.497 C 45.39 58.188 43.647 57.146 42.2 55.211 C 41.971 54.903 41.756 54.585 41.557 54.257 C 40.579 55.735 39.328 56.814 37.939 57.518 C 36.622 58.187 35.184 58.513 33.741 58.519 C 32.307 58.524 30.869 58.214 29.545 57.612 C 27.945 56.883 26.5 55.726 25.411 54.179 C 24.006 55.985 21.634 57.694 19.001 58.722 C 16.088 59.859 12.812 60.197 10.096 58.968 L 10.92 57.018 Z" style="fill: rgb(30, 130, 255);"/>
+</svg>
\ No newline at end of file
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="55" height="63">
+ <defs>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__e">
+ <feMorphology radius="2" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__g">
+ <feMorphology radius="1.08" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__i">
+ <feMorphology radius="1.44" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <path
+ d="M22.528 23C20.887 23 11 38.241 11 44.803c0 5.174 2.987 10.572 11.528 10.572 7.82 0 11.528-5.346 11.528-10.572C34.056 38.158 24.169 23 22.528 23z"
+ id="prefix__a" />
+ <path
+ d="M10.125 5C9.253 5 4 13.238 4 16.785c0 2.797 1.587 5.715 6.125 5.715 4.155 0 6.125-2.89 6.125-5.715C16.25 13.193 10.997 5 10.125 5z"
+ id="prefix__b" />
+ <path
+ d="M35.313 0C34.129 0 27 11.122 27 15.91c0 3.776 2.154 7.715 8.313 7.715 5.64 0 8.312-3.901 8.312-7.715 0-4.849-7.129-15.91-8.313-15.91z"
+ id="prefix__c" />
+ <mask id="prefix__f" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-2" y="-2" width="27.056"
+ height="36.375">
+ <path fill="#fff" d="M9 21h27.056v36.375H9z" />
+ <use xlink:href="#prefix__a" />
+ </mask>
+ <mask id="prefix__h" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.08" y="-1.08"
+ width="14.41" height="19.66">
+ <path fill="#fff" d="M2.92 3.92h14.41v19.66H2.92z" />
+ <use xlink:href="#prefix__b" />
+ </mask>
+ <mask id="prefix__j" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.44" y="-1.44"
+ width="19.505" height="26.505">
+ <path fill="#fff" d="M25.56-1.44h19.505v26.505H25.56z" />
+ <use xlink:href="#prefix__c" />
+ </mask>
+ <rect id="prefix__d" x="-8.105" y="28.395" width="67" height="4" rx="2" />
+ </defs>
+ <g transform="translate(2 2)" fill="none" fill-rule="evenodd">
+ <use height="100%" width="100%" xlink:href="#prefix__a" fill="#000" filter="url(#prefix__e)" />
+ <use height="100%" width="100%" xlink:href="#prefix__a" fill="#55a4ff" fill-opacity=".3" />
+ <use height="100%" width="100%" xlink:href="#prefix__a" mask="url(#prefix__f)" stroke="#fff" stroke-width="4" />
+ </g>
+ <g transform="translate(2 2)" fill="none" fill-rule="evenodd">
+ <use height="100%" width="100%" xlink:href="#prefix__b" fill="#000" filter="url(#prefix__g)" />
+ <use height="100%" width="100%" xlink:href="#prefix__b" fill="#55a4ff" fill-opacity=".3" />
+ <use height="100%" width="100%" xlink:href="#prefix__b" mask="url(#prefix__h)" stroke="#fff"
+ stroke-width="2.16" />
+ </g>
+ <g transform="translate(2 2)" fill="none" fill-rule="evenodd">
+ <use height="100%" width="100%" xlink:href="#prefix__c" fill="#000" filter="url(#prefix__i)" />
+ <use height="100%" width="100%" xlink:href="#prefix__c" fill="#55a4ff" fill-opacity=".3" />
+ <use height="100%" width="100%" xlink:href="#prefix__c" mask="url(#prefix__j)" stroke="#fff"
+ stroke-width="2.88" />
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" height="600" width="600" data-name="Calque 1">
+ <path fill="#005892" d="M0 0h600v600H0z" />
+ <rect x="220.481" y="111.57" width="159.038" height="159.038" rx="12.759" ry="12.759" fill="#fff" />
+ <path fill="#005891" d="M334.557 134.05l17.013 17.697-24.152 6.152z" />
+ <path
+ d="M357.95 191.089a57.646 57.646 0 00-10.178-32.81l-5.164 1.974a56.05 56.05 0 0110.253 30.836 53.165 53.165 0 01-45.57 52.329 210.152 210.152 0 01-1.747-104.81 55.443 55.443 0 0119.747 6l1.291-4.861a57.57 57.57 0 00-19.747-6.152 150.684 150.684 0 018.127-22.025h-7.595a164.05 164.05 0 00-7.595 21.645 57.95 57.95 0 000 115.823h1.975c1.975 7.063 4.253 14.278 7.063 21.646h7.063c-2.886-7.595-5.392-15.19-7.595-22.254a57.95 57.95 0 0049.671-57.341z"
+ fill="#005891" />
+ <path d="M298.633 130.405h-7.063" fill="#fff" />
+ <g fill="#fff">
+ <path
+ d="M123.418 315.342h22.025l14.582 44.126 14.05-44.126h22.102l7.975 76.48H182.05l-3.266-38.278-11.317 38.279h-15.873l-11.317-38.279-4.48 38.279H114zM268.405 372.608h-34.709v-10.254h26.279V346.33H233.24v-11.544h35.164v-19.443h-56.278v76.48h56.278zM403.975 372.608H369.19v-10.254h26.278V346.33h-26.734v-11.544h35.24v-19.443H347.62v76.48h56.355zM297.038 391.823h21.19v-57.038h18.76v-19.443h-59.165v19.443h19.215zM448.101 314.658a37.975 37.975 0 1037.975 37.975 37.975 37.975 0 00-37.975-37.975zm0 57.494a19.443 19.443 0 1119.443-19.443 19.443 19.443 0 01-19.443 19.443zM134.962 464.127h23.696v-14.81h-23.696v-14.963h30.684v-18.607H114v72.607h20.962zM213.57 458.81s10.936-1.215 10.936-21.19a19.519 19.519 0 00-18.835-21.873h-34.86v72.607h17.695V461.62h6.532l11.165 26.734h20.886zm-11.848-11.544h-13.52v-17.469h13.52a9.494 9.494 0 010 17.469zM274.025 415.747h-16.253l-27.418 72.607h20.735l5.392-13.519h19.975l4.557 13.52h19.822zm-15.19 45.114l6.988-19.52 6.987 19.52zM321.494 449.316l26.05 39.038h16.785v-72.607h-18.911v42.456l-24.152-42.456h-18.38v72.607h18.608zM418.253 465.038a18.38 18.38 0 11-.987-26.43l11.848-13.292a36.076 36.076 0 100 53.773zM486 470.127h-33.038v-9.722h24.987V445.14h-25.443v-10.936H486V415.67h-53.544v72.76H486z" />
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
+ <path
+ d="m32 2.5c.98 0 1.76.79 1.76 1.76v8.25l2.82-4.09c.35-.5.9-.77 1.47-.76.34 0 .68.11.98.31.8.55 1.01 1.65.45 2.45l-5.73 8.31v3.56 6.66l8.85-5.11 4.33-9.11c.42-.88 1.47-1.25 2.35-.84.33.16.59.4.76.7.29.49.33 1.1.07 1.65l-2.13 4.49 7.15-4.13c.85-.49 1.92-.2 2.41.65.49.85.2 1.92-.65 2.41l-7.15 4.13 4.96.4c.61.05 1.12.4 1.4.89.17.3.25.64.22 1.01-.08.97-.92 1.69-1.9 1.62l-10.06-.8-8.84 5.09 5.77 3.33 3.08 1.78 10.06-.8c.97-.08 1.82.64 1.9 1.62.03.36-.05.71-.22 1.01-.28.49-.79.84-1.4.89l-4.96.4 7.15 4.13c.85.49 1.13 1.56.65 2.41-.49.85-1.56 1.13-2.41.64l-7.15-4.13 2.13 4.49c.26.55.22 1.17-.07 1.65-.17.29-.43.54-.76.69-.88.42-1.93.05-2.35-.83l-4.33-9.11-8.85-5.11v6.66 3.56l5.73 8.31c.55.8.35 1.9-.45 2.45-.3.21-.64.31-.98.31-.57.01-1.12-.26-1.47-.76l-2.82-4.09v8.25c0 .98-.79 1.76-1.76 1.76-.98 0-1.76-.79-1.76-1.76v-8.25l-2.82 4.09c-.35.5-.9.77-1.47.76-.34 0-.68-.11-.98-.31-.8-.55-1.01-1.65-.45-2.45l5.73-8.31v-3.56-6.66l-5.77 3.33-3.08 1.78-4.33 9.11c-.42.88-1.47 1.25-2.35.83-.33-.16-.59-.4-.76-.69-.29-.49-.33-1.1-.07-1.65l2.14-4.49-7.15 4.13c-.85.49-1.92.2-2.41-.64-.49-.85-.2-1.92.64-2.41l7.15-4.13-4.96-.4c-.61-.05-1.12-.4-1.4-.89-.17-.3-.25-.64-.22-1.01.08-.97.92-1.69 1.9-1.62l10.06.8 3.08-1.78 5.75-3.33-8.85-5.11-10.06.8c-.97.08-1.82-.64-1.9-1.62-.03-.36.05-.71.22-1.01.28-.49.79-.84 1.4-.89l4.96-.4-7.15-4.11c-.85-.49-1.13-1.56-.64-2.41.49-.85 1.56-1.13 2.41-.65l7.15 4.13-2.14-4.49c-.26-.55-.22-1.17.07-1.65.17-.29.43-.54.76-.7.88-.42 1.93-.05 2.35.84l4.33 9.11 8.85 5.11v-6.66-3.56l-5.73-8.31c-.55-.8-.35-1.9.45-2.45.3-.21.64-.31.98-.31.57-.01 1.12.26 1.47.76l2.82 4.09v-8.25c.01-.97.79-1.76 1.77-1.76"
+ fill="#dae1e4" />
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <g transform="matrix(0.109429, 0, 0, 0.095795, 3.683853, 5.87504)" style="">
+ <polygon style="fill:#FFDA44;" points="225.584 244.867 174.304 380.884 268.543 380.884 209.837 509.421 367.316 333.616 271.782 333.616 303.985 244.867"/>
+ <polygon style="fill:#CCA400;" points="304.519 244.867 226.118 244.867 207.482 294.3 286.581 294.3"/>
+ <path style="fill:#B8D6FD;" d="M 459.559 266.555 C 488.522 266.555 512.001 243.077 512.001 214.113 C 512.001 185.149 488.523 161.671 459.559 161.671 C 450.829 161.671 442.605 163.816 435.364 167.589 C 428.157 153.316 416.099 141.917 401.341 135.574 C 401.341 135.443 401.351 135.316 401.351 135.185 C 401.351 62.632 342.535 3.817 269.982 3.817 C 209.899 3.817 159.273 44.169 143.634 99.239 C 109.041 105.309 81.724 132.452 75.398 166.956 C 68.464 163.574 60.675 161.671 52.44 161.671 C 23.479 161.672 0 185.15 0 214.114 C 0 243.078 23.479 266.556 52.442 266.556 L 459.559 266.556 L 459.559 266.555 Z"/>
+ <path style="opacity:0.41;fill:#6AB3EA;enable-background:new ;" d="M 458.404 160.434 C 449.674 160.434 441.45 162.579 434.209 166.352 C 427.002 152.079 414.944 140.68 400.186 134.337 C 400.186 134.206 400.196 134.079 400.196 133.948 C 400.196 61.395 341.38 2.58 268.827 2.58 C 257.171 2.58 245.875 4.105 235.117 6.955 C 291.333 21.84 332.772 73.052 332.772 133.95 C 332.772 134.081 332.763 134.208 332.762 134.339 C 347.519 140.681 359.578 152.081 366.785 166.354 C 374.026 162.58 382.25 160.436 390.98 160.436 C 419.943 160.436 443.422 183.914 443.422 212.878 C 443.422 241.841 419.944 265.32 390.98 265.32 L 458.404 265.32 C 487.367 265.32 510.846 241.841 510.846 212.878 C 510.846 183.912 487.367 160.434 458.404 160.434 Z"/>
+ <g style="opacity:0.41;">
+ <path style="fill:#6AB3EA;" d="M258.252,34.812c0,3.364-2.216,6.456-5.612,7.421c-40.109,11.389-68.121,48.482-68.121,90.201 c0,4.264-3.455,7.718-7.718,7.718s-7.718-3.455-7.718-7.718c0-48.587,32.626-91.785,79.341-105.052 c4.1-1.165,8.369,1.216,9.534,5.316C258.157,33.404,258.252,34.114,258.252,34.812z"/>
+ </g>
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <path fill="#F8EFE0" d="M 11.018 52.475 L 11.018 31.819 C 7.317 33.065 4.779 29.687 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 51.937 51.358 C 43.944 54.785 42.3 46.755 42.28 46.918 C 41.461 53.613 28.847 53.227 26.809 48.767 C 26.439 47.958 26.67 47.804 26.141 47.766 C 23.045 47.544 22.868 55.347 11.018 52.475 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
+ <path fill="#D93133" d="M 11.018 31.819 C 10.054 32.144 9.151 32.151 8.401 31.927 C 7.816 31.754 7.322 31.444 6.959 31.043 C 6.596 30.643 6.366 30.156 6.295 29.618 C 6.188 28.785 6.472 27.843 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 49.63 30.982 C 49.63 30.618 33.464 19.43 31.679 18.213 C 29.788 19.473 13.326 30.571 13.326 31.04 L 11.018 31.819 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
+ <path fill="#313A58" d="M 31.595 25.496 C 33.228 25.496 34.711 26.081 35.784 27.021 C 36.861 27.963 37.526 29.076 37.526 30.503 L 37.526 35.325 L 25.662 35.325 L 25.662 30.503 C 25.662 29.073 26.33 27.961 27.404 27.021 C 28.479 26.081 29.963 25.496 31.595 25.496 Z" style=""/>
+ <path fill="#ABB9BC" d="M 32.111 31.421 L 32.111 34.426 L 36.496 34.426 L 36.496 31.421 L 32.111 31.421 Z M 32.111 26.424 L 32.111 30.517 L 36.496 30.517 L 36.496 30.505 C 36.496 29.326 35.945 28.439 35.056 27.661 C 34.282 26.983 33.252 26.529 32.111 26.424 Z M 31.079 30.517 L 31.079 26.424 C 29.936 26.531 28.909 26.983 28.134 27.661 C 27.245 28.439 26.694 29.326 26.694 30.505 L 26.694 30.517 L 31.079 30.517 Z M 31.079 34.423 L 31.079 31.421 L 26.694 31.421 L 26.694 34.426 L 31.079 34.426 L 31.079 34.423 Z" style=""/>
+ <path fill="#313A58" d="M 51.92 31.732 L 49.64 30.959 L 49.64 52.389 L 51.92 52.389 L 51.92 31.732 Z M 10.908 31.819 L 13.189 31.046 L 13.189 52.476 L 10.908 52.476 L 10.908 31.819 Z" style=""/>
+ <path d="M 11.097 51.603 C 13.269 52.586 15.988 52.276 18.451 51.315 C 21.367 50.176 23.866 48.168 24.668 46.318 C 24.9 45.781 25.509 45.54 26.029 45.779 C 26.259 45.885 26.444 46.075 26.547 46.312 C 27.432 48.152 28.886 49.487 30.554 50.246 C 31.623 50.733 32.775 50.983 33.918 50.978 C 35.051 50.973 36.18 50.717 37.211 50.195 C 38.688 49.446 39.974 48.13 40.802 46.195 C 41.031 45.656 41.641 45.412 42.163 45.649 C 42.416 45.764 42.614 45.978 42.711 46.245 C 43.106 47.121 43.54 47.869 44.009 48.496 C 45.11 49.969 46.402 50.756 47.805 50.981 C 49.259 51.215 50.874 50.868 52.56 50.07 C 53.763 49.501 55 48.701 56.239 47.714 L 57.499 49.397 C 56.142 50.478 54.77 51.363 53.416 52.004 C 51.373 52.971 49.365 53.383 47.49 53.082 C 45.567 52.773 43.824 51.731 42.377 49.796 C 42.148 49.488 41.933 49.17 41.734 48.842 C 40.756 50.32 39.505 51.399 38.116 52.103 C 36.799 52.772 35.361 53.098 33.918 53.104 C 32.484 53.109 31.046 52.799 29.722 52.197 C 28.122 51.468 26.677 50.311 25.588 48.764 C 24.183 50.57 21.811 52.279 19.178 53.307 C 16.265 54.444 12.989 54.782 10.273 53.553 L 11.097 51.603 Z" style="fill: rgb(30, 130, 255);"/>
+ <path d="M 8.218 34.7 C 8.218 34.7 8.173 34.7 8.13 34.7 C 8.041 34.7 7.997 34.7 7.953 34.64 L 7.908 34.64 C 6.888 34.399 6.046 33.017 5.958 31.515 L 5.958 31.034 C 6.003 30.794 6.046 30.494 6.091 30.192 C 6.18 30.013 6.268 29.772 6.357 29.532 L 6.667 28.93 C 7.376 27.789 7.953 26.648 8.351 25.445 C 8.794 26.888 9.504 28.15 10.08 29.111 C 10.124 29.231 10.213 29.411 10.346 29.592 C 10.434 29.832 10.567 30.133 10.701 30.373 C 10.745 30.553 10.789 30.854 10.834 31.094 L 10.834 31.455 C 10.834 31.515 10.834 31.575 10.834 31.635 C 10.834 31.635 10.834 31.695 10.834 31.695 L 10.834 31.756 L 10.834 31.815 C 10.701 33.138 9.903 34.399 8.928 34.64 L 8.883 34.64 C 8.839 34.64 8.794 34.7 8.706 34.7 C 8.661 34.7 8.618 34.7 8.618 34.7 L 8.218 34.7" fill="#1e82ff" style=""/>
+ <path d="M 17.152 21.924 C 17.152 21.924 17.107 21.924 17.064 21.924 C 16.975 21.924 16.931 21.924 16.887 21.864 L 16.842 21.864 C 15.822 21.623 14.98 20.241 14.892 18.739 L 14.892 18.258 C 14.937 18.018 14.98 17.718 15.025 17.416 C 15.114 17.237 15.202 16.996 15.291 16.756 L 15.601 16.154 C 16.31 15.013 16.887 13.872 17.285 12.669 C 17.728 14.112 18.438 15.374 19.014 16.335 C 19.058 16.455 19.147 16.635 19.28 16.816 C 19.368 17.056 19.501 17.357 19.635 17.597 C 19.679 17.777 19.723 18.078 19.768 18.318 L 19.768 18.679 C 19.768 18.739 19.768 18.799 19.768 18.859 C 19.768 18.859 19.768 18.919 19.768 18.919 L 19.768 18.98 L 19.768 19.039 C 19.635 20.362 18.837 21.623 17.862 21.864 L 17.817 21.864 C 17.773 21.864 17.728 21.924 17.64 21.924 C 17.595 21.924 17.552 21.924 17.552 21.924 L 17.152 21.924" fill="#1e82ff" style=""/>
+ <path d="M 42.51 27.949 C 42.51 27.949 42.465 27.949 42.422 27.949 C 42.333 27.949 42.289 27.949 42.245 27.889 L 42.2 27.889 C 41.18 27.648 40.338 26.266 40.25 24.764 L 40.25 24.283 C 40.295 24.043 40.338 23.743 40.383 23.441 C 40.472 23.262 40.56 23.021 40.649 22.781 L 40.959 22.179 C 41.668 21.038 42.245 19.897 42.643 18.694 C 43.086 20.137 43.796 21.399 44.372 22.36 C 44.416 22.48 44.505 22.66 44.638 22.841 C 44.726 23.081 44.859 23.382 44.993 23.622 C 45.037 23.802 45.081 24.103 45.126 24.343 L 45.126 24.704 C 45.126 24.764 45.126 24.824 45.126 24.884 C 45.126 24.884 45.126 24.944 45.126 24.944 L 45.126 25.005 L 45.126 25.064 C 44.993 26.387 44.195 27.648 43.22 27.889 L 43.175 27.889 C 43.131 27.889 43.086 27.949 42.998 27.949 C 42.953 27.949 42.91 27.949 42.91 27.949 L 42.51 27.949" fill="#1e82ff" style=""/>
+ <path d="M 30.168 12.518 C 30.168 12.518 30.123 12.518 30.08 12.518 C 29.991 12.518 29.947 12.518 29.903 12.458 L 29.858 12.458 C 28.838 12.217 27.996 10.835 27.908 9.333 L 27.908 8.852 C 27.953 8.612 27.996 8.312 28.041 8.01 C 28.13 7.831 28.218 7.59 28.307 7.35 L 28.617 6.748 C 29.326 5.607 29.903 4.466 30.301 3.263 C 30.744 4.706 31.454 5.968 32.03 6.929 C 32.074 7.049 32.163 7.229 32.296 7.41 C 32.384 7.65 32.517 7.951 32.651 8.191 C 32.695 8.371 32.739 8.672 32.784 8.912 L 32.784 9.273 C 32.784 9.333 32.784 9.393 32.784 9.453 C 32.784 9.453 32.784 9.513 32.784 9.513 L 32.784 9.574 L 32.784 9.633 C 32.651 10.956 31.853 12.217 30.878 12.458 L 30.833 12.458 C 30.789 12.458 30.744 12.518 30.656 12.518 C 30.611 12.518 30.568 12.518 30.568 12.518 L 30.168 12.518" fill="#1e82ff" style=""/>
+ <path d="M 54.328 36.78 C 54.328 36.78 54.283 36.78 54.24 36.78 C 54.151 36.78 54.107 36.78 54.063 36.72 L 54.018 36.72 C 52.998 36.479 52.156 35.097 52.068 33.595 L 52.068 33.114 C 52.113 32.874 52.156 32.574 52.201 32.272 C 52.29 32.093 52.378 31.852 52.467 31.612 L 52.777 31.01 C 53.486 29.869 54.063 28.728 54.461 27.525 C 54.904 28.968 55.614 30.23 56.19 31.191 C 56.234 31.311 56.323 31.491 56.456 31.672 C 56.544 31.912 56.677 32.213 56.811 32.453 C 56.855 32.633 56.899 32.934 56.944 33.174 L 56.944 33.535 C 56.944 33.595 56.944 33.655 56.944 33.715 C 56.944 33.715 56.944 33.775 56.944 33.775 L 56.944 33.836 L 56.944 33.895 C 56.811 35.218 56.013 36.479 55.038 36.72 L 54.993 36.72 C 54.949 36.72 54.904 36.78 54.816 36.78 C 54.771 36.78 54.728 36.78 54.728 36.78 L 54.328 36.78" fill="#1e82ff" style=""/>
+ <path d="M 10.92 57.018 C 13.092 58.001 15.811 57.691 18.274 56.73 C 21.19 55.591 23.689 53.583 24.491 51.733 C 24.723 51.196 25.332 50.955 25.852 51.194 C 26.082 51.3 26.267 51.49 26.37 51.727 C 27.255 53.567 28.709 54.902 30.377 55.661 C 31.446 56.148 32.598 56.398 33.741 56.393 C 34.874 56.388 36.003 56.132 37.034 55.61 C 38.511 54.861 39.797 53.545 40.625 51.61 C 40.854 51.071 41.464 50.827 41.986 51.064 C 42.239 51.179 42.437 51.393 42.534 51.66 C 42.929 52.536 43.363 53.284 43.832 53.911 C 44.933 55.384 46.225 56.171 47.628 56.396 C 49.082 56.63 50.697 56.283 52.383 55.485 C 53.586 54.916 54.823 54.116 56.062 53.129 L 57.322 54.812 C 55.965 55.893 54.593 56.778 53.239 57.419 C 51.196 58.386 49.188 58.798 47.313 58.497 C 45.39 58.188 43.647 57.146 42.2 55.211 C 41.971 54.903 41.756 54.585 41.557 54.257 C 40.579 55.735 39.328 56.814 37.939 57.518 C 36.622 58.187 35.184 58.513 33.741 58.519 C 32.307 58.524 30.869 58.214 29.545 57.612 C 27.945 56.883 26.5 55.726 25.411 54.179 C 24.006 55.985 21.634 57.694 19.001 58.722 C 16.088 59.859 12.812 60.197 10.096 58.968 L 10.92 57.018 Z" style="fill: rgb(30, 130, 255);"/>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <path d="M 10.382 37.307 C 12.554 38.29 15.273 37.98 17.736 37.019 C 20.652 35.88 23.151 33.872 23.953 32.022 C 24.185 31.485 24.794 31.244 25.314 31.483 C 25.544 31.589 25.729 31.779 25.832 32.016 C 26.717 33.856 28.171 35.191 29.839 35.95 C 30.908 36.437 32.06 36.687 33.203 36.682 C 34.336 36.677 35.465 36.421 36.496 35.899 C 37.973 35.15 39.259 33.834 40.087 31.899 C 40.316 31.36 40.926 31.116 41.448 31.353 C 41.701 31.468 41.899 31.682 41.996 31.949 C 42.391 32.825 42.825 33.573 43.294 34.2 C 44.395 35.673 45.687 36.46 47.09 36.685 C 48.544 36.919 50.159 36.572 51.845 35.774 C 53.048 35.205 54.285 34.405 55.524 33.418 L 56.784 35.101 C 55.427 36.182 54.055 37.067 52.701 37.708 C 50.658 38.675 48.65 39.087 46.775 38.786 C 44.852 38.477 43.109 37.435 41.662 35.5 C 41.433 35.192 41.218 34.874 41.019 34.546 C 40.041 36.024 38.79 37.103 37.401 37.807 C 36.084 38.476 34.646 38.802 33.203 38.808 C 31.769 38.813 30.331 38.503 29.007 37.901 C 27.407 37.172 25.962 36.015 24.873 34.468 C 23.468 36.274 21.096 37.983 18.463 39.011 C 15.55 40.148 12.274 40.486 9.558 39.257 L 10.382 37.307 Z" style="fill: rgb(30, 130, 255);"/>
+ <path d="M 10.205 42.722 C 12.377 43.705 15.096 43.395 17.559 42.434 C 20.475 41.295 22.974 39.287 23.776 37.437 C 24.008 36.9 24.617 36.659 25.137 36.898 C 25.367 37.004 25.552 37.194 25.655 37.431 C 26.54 39.271 27.994 40.606 29.662 41.365 C 30.731 41.852 31.883 42.102 33.026 42.097 C 34.159 42.092 35.288 41.836 36.319 41.314 C 37.796 40.565 39.082 39.249 39.91 37.314 C 40.139 36.775 40.749 36.531 41.271 36.768 C 41.524 36.883 41.722 37.097 41.819 37.364 C 42.214 38.24 42.648 38.988 43.117 39.615 C 44.218 41.088 45.51 41.875 46.913 42.1 C 48.367 42.334 49.982 41.987 51.668 41.189 C 52.871 40.62 54.108 39.82 55.347 38.833 L 56.607 40.516 C 55.25 41.597 53.878 42.482 52.524 43.123 C 50.481 44.09 48.473 44.502 46.598 44.201 C 44.675 43.892 42.932 42.85 41.485 40.915 C 41.256 40.607 41.041 40.289 40.842 39.961 C 39.864 41.439 38.613 42.518 37.224 43.222 C 35.907 43.891 34.469 44.217 33.026 44.223 C 31.592 44.228 30.154 43.918 28.83 43.316 C 27.23 42.587 25.785 41.43 24.696 39.883 C 23.291 41.689 20.919 43.398 18.286 44.426 C 15.373 45.563 12.097 45.901 9.381 44.672 L 10.205 42.722 Z" style="fill: rgb(30, 130, 255);"/>
+ <path d="M 32.307 33.157 C 30.008 33.038 27.346 31.638 25.776 29.76 C 25.48 29.421 25.206 29.064 24.956 28.688 C 23.585 30.561 21.153 32.357 18.438 33.424 C 15.546 34.563 12.297 34.903 9.61 33.677 L 10.301 32.03 C 12.342 32.962 14.845 32.775 17.183 31.979 C 17.253 28.669 18.202 25.534 19.838 22.875 C 21.336 20.442 23.646 18.223 26.281 16.786 C 29.429 15.07 33.861 14.165 36.905 16.582 C 40.064 19.088 39.596 23.333 36.462 25.669 C 35.744 26.203 34.894 26.543 34.027 26.631 C 33.319 26.702 32.602 26.606 31.934 26.309 C 31.263 26.011 30.648 25.518 30.154 24.801 C 29.581 23.968 29.17 22.827 29.031 21.336 C 28.992 20.904 29.296 20.523 29.711 20.48 C 30.125 20.44 30.493 20.757 30.532 21.188 C 30.643 22.376 30.953 23.26 31.383 23.885 C 31.708 24.357 32.102 24.676 32.525 24.866 C 32.954 25.056 33.42 25.116 33.885 25.069 C 34.48 25.009 35.072 24.769 35.582 24.39 C 37.883 22.674 38.346 19.7 35.99 17.83 C 26.886 12.683 22.711 27.316 31.469 31.199 C 32.079 31.342 32.703 31.412 33.329 31.411 C 34.495 31.407 35.656 31.142 36.717 30.6 C 38.239 29.821 39.562 28.459 40.413 26.455 C 40.605 26 41.116 25.793 41.554 25.994 C 41.766 26.091 41.931 26.272 42.013 26.498 C 42.418 27.404 42.863 28.177 43.343 28.823 C 44.48 30.357 45.818 31.177 47.274 31.413 C 48.771 31.655 50.429 31.298 52.154 30.475 C 53.379 29.893 54.635 29.073 55.89 28.065 L 56.947 29.488 C 55.592 30.576 54.222 31.465 52.872 32.109 C 50.847 33.075 48.86 33.487 47.01 33.188 C 45.117 32.881 43.402 31.847 41.976 29.924 C 41.694 29.542 41.434 29.145 41.197 28.733 C 40.211 30.324 38.919 31.474 37.476 32.212 C 36.175 32.876 34.753 33.201 33.329 33.207 C 32.988 33.209 32.647 33.192 32.307 33.157 Z" style="fill: rgb(30, 130, 255);"/>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
+ <path
+ d="m61.55 22.14c-3.06-.84-7.3-2.16-9.33-3.51-3.39-2.25-4.77-2.26-7.12-3.02-2.35-.76-4.78-2.08-4.78-2.08s-2.57-2.17-6.5-2.77c-3.92-.6-5.65-2.61-5.65-2.61s-.6-1.38-2.2-1.96c-2.54-1.01-6.25 2.29-8.28 7.38-2.03 5.09-1.61 10.04.94 11.05 0 0 6.32 2.52 10.66 2.08 4.34-.44 7.8.39 7.8.39s3.64.85 7.37.58c3.72-.27 6.09.62 6.09.62s2.41.67 10.18.27c.31-.43.57-.91.77-1.43.67-1.69.64-3.47.05-4.99z"
+ fill="#db5336" stroke="#db5336" stroke-miterlimit="10" />
+ <ellipse transform="matrix(-.929-.37.37-.929 37.3113 37.9507)" cx="22.3" cy="15.4" rx="4.96" ry="9.92"
+ fill="#ca2a14" />
+ <g fill="#fff">
+ <path
+ d="m61.55 22.14c-1.77-.48-3.92-1.13-5.82-1.84.77 1.74.88 3.69.16 5.5-.46 1.15-1.2 2.1-2.12 2.84 1.58.07 3.84.09 6.97-.07.31-.43.57-.91.77-1.43.66-1.7.63-3.48.04-5" />
+ <path
+ d="m50.1 17.36c-1.98-1.03-3.21-1.17-5-1.75-.5-.16-1.01-.35-1.49-.54 1.27 2.47 1.49 5.53.35 8.41-.67 1.68-1.73 3.09-3.01 4.15 1.08.08 2.29.12 3.51.03 1.07-.08 2.02-.06 2.84.01 1.21-.93 2.19-2.2 2.8-3.73.89-2.21.82-4.56 0-6.58" />
+ <path
+ d="m37.81 12c-1.06-.5-2.42-1-3.99-1.24-.84-.13-1.57-.32-2.22-.54 1.6 2.52 1.73 6.77.05 10.99-.89 2.24-2.16 4.14-3.59 5.53.42 0 .83-.01 1.23-.05 1.8-.18 3.45-.15 4.76-.04 1.75-1.09 3.32-2.98 4.29-5.4 1.4-3.53 1.1-7.14-.53-9.25" />
+ <path
+ d="m24.53 15.02c-1.09 2.73-1.32 5.44-.8 7.43 1.21-1.31 2.34-3.11 3.18-5.22 1.08-2.72 1.47-5.4 1.2-7.46-1.4 1.19-2.7 3.02-3.58 5.25" />
+ </g>
+ <g fill="none" stroke="#1a171b" stroke-miterlimit="10">
+ <path d="m13.55 10.5 4.7 2.19" />
+ <path d="m13.55 10.5 13.28-3.87" />
+ <path d="m13.55 10.5 8.74 13.45" />
+ <path d="M 13.55,10.5 7,9" />
+ </g>
+ <path d="M4.5,59.5V9c0-1.38,1.12-2.5,2.5-2.5S9.5,7.62,9.5,9c0,1.21-0.86,2.22-2,2.45V59.5H4.5z" fill="#8b96ac" />
+ <path
+ d="m7 7c1.1 0 2 0.9 2 2s-0.9 2-2 2v48h-2v-50c0-1.1 0.9-2 2-2m0-1c-1.65 0-3 1.35-3 3v51h4v-48.17c1.16-0.41 2-1.52 2-2.83 0-1.65-1.35-3-3-3z"
+ fill="#676b72" />
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.openhab.addons.bundles</groupId>
+ <artifactId>org.openhab.addons.reactor.bundles</artifactId>
+ <version>4.3.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.openhab.binding.meteofrance</artifactId>
+
+ <name>openHAB Add-ons :: Bundles :: Meteo France Binding</name>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<features name="org.openhab.binding.meteofrance-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
+ <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
+
+ <feature name="openhab-binding-meteofrance" description="Meteo France Binding" version="${project.version}">
+ <feature>openhab-runtime-base</feature>
+ <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.meteofrance/${project.version}</bundle>
+ </feature>
+</features>
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+
+/**
+ * The {@link MeteoFranceBindingConstants} class defines common constants, which are
+ * used across the whole binding.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class MeteoFranceBindingConstants {
+ public static final String BINDING_ID = "meteofrance";
+ public static final String LOCAL = "local";
+ public static final int REQUEST_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(45);
+
+ // List of Bridge Type UIDs
+ public static final ThingTypeUID BRIDGE_TYPE_API = new ThingTypeUID(BINDING_ID, "api");
+
+ // List of all Thing Type UIDs
+ public static final ThingTypeUID THING_TYPE_VIGILANCE = new ThingTypeUID(BINDING_ID, "vigilance");
+ public static final ThingTypeUID THING_TYPE_RAIN_FORECAST = new ThingTypeUID(BINDING_ID, "rain-forecast");
+
+ // List of all Channel IDs
+
+ public static final String OBSERVATION_TIME = "observation-time";
+ public static final String UPDATE_TIME = "update-time";
+ public static final String INTENSITY = "intensity";
+
+ public static final String END_TIME = "end-time";
+ public static final String COMMENT = "comment";
+
+ public static final Set<ThingTypeUID> DISCOVERABLE_THING_TYPES_UIDS = Set.of(THING_TYPE_VIGILANCE,
+ THING_TYPE_RAIN_FORECAST);
+ public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream
+ .of(Set.of(BRIDGE_TYPE_API), DISCOVERABLE_THING_TYPES_UIDS).flatMap(Set::stream)
+ .collect(Collectors.toSet());
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * An exception that occurred while communicating with Meteo France API server or related processes.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class MeteoFranceException extends Exception {
+
+ private static final long serialVersionUID = 7613161188837438233L;
+
+ public MeteoFranceException(String format, Object... args) {
+ super(format.formatted(args));
+ }
+
+ public MeteoFranceException(Exception e, String format, Object... args) {
+ super(format.formatted(args), e);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal;
+
+import static org.openhab.binding.meteofrance.internal.MeteoFranceBindingConstants.*;
+
+import java.time.ZoneId;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.meteofrance.internal.db.DepartmentDbService;
+import org.openhab.binding.meteofrance.internal.deserialization.MeteoFranceDeserializer;
+import org.openhab.binding.meteofrance.internal.handler.MeteoFranceBridgeHandler;
+import org.openhab.binding.meteofrance.internal.handler.RainForecastHandler;
+import org.openhab.binding.meteofrance.internal.handler.VigilanceHandler;
+import org.openhab.core.i18n.LocationProvider;
+import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.core.thing.Bridge;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.binding.BaseThingHandlerFactory;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerFactory;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * The {@link MeteoFranceHandlerFactory} is responsible for creating things and thing handlers.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@Component(service = ThingHandlerFactory.class)
+@NonNullByDefault
+public class MeteoFranceHandlerFactory extends BaseThingHandlerFactory {
+ private final MeteoFranceIconProvider iconProvider;
+ private final MeteoFranceDeserializer deserializer;
+ private final ZoneId zoneId;
+
+ @Activate
+ public MeteoFranceHandlerFactory(final @Reference TimeZoneProvider timeZoneProvider,
+ final @Reference LocationProvider locationProvider, final @Reference DepartmentDbService dbService,
+ final @Reference MeteoFranceIconProvider iconProvider,
+ final @Reference MeteoFranceDeserializer deserializer) {
+ this.iconProvider = iconProvider;
+ this.deserializer = deserializer;
+ this.zoneId = timeZoneProvider.getTimeZone();
+ }
+
+ @Override
+ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
+ return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
+ }
+
+ @Override
+ protected @Nullable ThingHandler createHandler(Thing thing) {
+ ThingTypeUID thingTypeUID = thing.getThingTypeUID();
+
+ return BRIDGE_TYPE_API.equals(thingTypeUID) ? new MeteoFranceBridgeHandler((Bridge) thing, deserializer)
+ : THING_TYPE_VIGILANCE.equals(thingTypeUID) ? new VigilanceHandler(thing, zoneId, iconProvider)
+ : THING_TYPE_RAIN_FORECAST.equals(thingTypeUID) ? new RainForecastHandler(thing, zoneId) : null;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal;
+
+import static org.openhab.binding.meteofrance.internal.MeteoFranceBindingConstants.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.meteofrance.internal.dto.Hazard;
+import org.openhab.binding.meteofrance.internal.dto.Risk;
+import org.openhab.core.i18n.TranslationProvider;
+import org.openhab.core.ui.icon.IconProvider;
+import org.openhab.core.ui.icon.IconSet;
+import org.openhab.core.ui.icon.IconSet.Format;
+import org.osgi.framework.BundleContext;
+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 MeteoFranceIconProvider} is the class providing binding related icons.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@Component(service = { IconProvider.class, MeteoFranceIconProvider.class })
+@NonNullByDefault
+public class MeteoFranceIconProvider implements IconProvider {
+ private static final String NEUTRAL_COLOR = "#3d3c3c";
+ private static final String DEFAULT_LABEL = "Météo France Icons";
+ private static final String DEFAULT_DESCRIPTION = "Icons illustrating weather alerts provided by Météo France";
+ private static final List<String> HAZARD_ICONS = Hazard.AS_SET.stream().filter(Hazard::isChannel)
+ .map(h -> h.channelName).toList();
+ private static final List<String> ICONS = Stream.concat(Stream.of("meteo_france", INTENSITY), HAZARD_ICONS.stream())
+ .toList();
+
+ private final Logger logger = LoggerFactory.getLogger(MeteoFranceIconProvider.class);
+ private final BundleContext context;
+ private final TranslationProvider i18nProvider;
+
+ @Activate
+ public MeteoFranceIconProvider(final BundleContext context, final @Reference TranslationProvider i18nProvider) {
+ this.context = context;
+ this.i18nProvider = i18nProvider;
+ }
+
+ @Override
+ public Set<IconSet> getIconSets() {
+ return getIconSets(null);
+ }
+
+ @Override
+ public Set<IconSet> getIconSets(@Nullable Locale locale) {
+ String label = getText("label", DEFAULT_LABEL, locale);
+ String description = getText("decription", DEFAULT_DESCRIPTION, locale);
+
+ return Set.of(new IconSet(BINDING_ID, label, description, Set.of(Format.SVG)));
+ }
+
+ private String getText(String entry, String defaultValue, @Nullable Locale locale) {
+ String text = defaultValue;
+ if (locale != null) {
+ text = i18nProvider.getText(context.getBundle(), "iconset." + entry, defaultValue, locale);
+ text = text == null ? defaultValue : text;
+ }
+ return text;
+ }
+
+ @Override
+ public @Nullable Integer hasIcon(String category, String iconSetId, Format format) {
+ return Format.SVG.equals(format) && iconSetId.equals(BINDING_ID) && ICONS.contains(category) ? 0 : null;
+ }
+
+ public @Nullable InputStream getIcon(String category, String state) {
+ return getIcon(category, BINDING_ID, state, Format.SVG);
+ }
+
+ @Override
+ public @Nullable InputStream getIcon(String category, String iconSetId, @Nullable String state, Format format) {
+ String iconName = category;
+ if (INTENSITY.equals(category) && state != null) {
+ String localState = "on".equalsIgnoreCase(state) ? "3" : "off".equalsIgnoreCase(state) ? "0" : state;
+ try {
+ iconName = "%s-%d".formatted(category, Double.valueOf(localState).intValue());
+ } catch (NumberFormatException e) {
+ logger.debug("Unable to parse {} to a numeric value", state);
+ }
+ }
+ String icon = getResource(iconName);
+ if (icon.isEmpty()) {
+ return null;
+ }
+
+ if (state != null && HAZARD_ICONS.contains(category)) {
+ try {
+ int ordinal = Integer.valueOf(state);
+ Risk alertLevel = ordinal < Risk.values().length ? Risk.values()[ordinal] : Risk.UNKNOWN;
+ icon = icon.replaceAll(NEUTRAL_COLOR, alertLevel.rgbColor);
+ } catch (NumberFormatException e) {
+ logger.debug("{} is not a valid DecimalType", state);
+ }
+ }
+
+ return new ByteArrayInputStream(icon.getBytes());
+ }
+
+ private String getResource(String iconName) {
+ String result = "";
+
+ URL iconResource = context.getBundle().getEntry("icon/%s.svg".formatted(iconName));
+ try (InputStream stream = iconResource.openStream()) {
+ result = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ logger.warn("Unable to load ressource '{}': {}", iconResource.getPath(), e.getMessage());
+ }
+ return result;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link BridgeConfiguration} is the class used to match the bridge configuration.
+ *
+ * @author Gaël L"hopital - Initial contribution
+ */
+@NonNullByDefault
+public class BridgeConfiguration {
+ public String apikey = "";
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link DepartmentConfiguration} is the class used to match the
+ * thing configuration.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class DepartmentConfiguration {
+ public static final String DEPARTMENT = "department";
+ public String department = "";
+ public int refresh = 60;
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link ForecastConfiguration} is the class used to match the rain forecast thing configuration.
+ *
+ * @author Gaël L"hopital - Initial contribution
+ */
+@NonNullByDefault
+public class ForecastConfiguration {
+ public static final String LOCATION = "location";
+
+ public String location = "";
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.db;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.library.types.PointType;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * The {@link DepartmentDbService} makes available a list of known French Metropolitan departments.
+ *
+ * @author Gaël L'hopital - Initial Contribution
+ */
+
+@Component(service = DepartmentDbService.class)
+@NonNullByDefault
+public class DepartmentDbService {
+ private final Logger logger = LoggerFactory.getLogger(DepartmentDbService.class);
+ private final List<Department> departments = new ArrayList<>();
+
+ public record Department(String id, String name, double northestLat, double southestLat, double eastestLon,
+ double westestLon) {
+ }
+
+ @Activate
+ public DepartmentDbService() {
+ try (InputStream is = Thread.currentThread().getContextClassLoader()
+ .getResourceAsStream("/db/departments.json");
+ Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) {
+ Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+ departments.addAll(Arrays.asList(gson.fromJson(reader, Department[].class)));
+ logger.debug("Successfully loaded {} departments", departments.size());
+ } catch (IOException | JsonSyntaxException | JsonIOException e) {
+ logger.warn("Unable to load departments list: {}", e.getMessage());
+ }
+ }
+
+ public List<Department> getBounding(PointType location) {
+ double latitude = location.getLatitude().doubleValue();
+ double longitude = location.getLongitude().doubleValue();
+ return departments.stream().filter(dep -> dep.northestLat >= latitude && dep.southestLat <= latitude
+ && dep.westestLon <= longitude && dep.eastestLon >= longitude).toList();
+ }
+
+ public @Nullable Department getDept(String deptId) {
+ return departments.stream().filter(dep -> dep.id.equalsIgnoreCase(deptId)).findFirst().orElse(null);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.deserialization;
+
+import java.time.ZonedDateTime;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.meteofrance.internal.MeteoFranceException;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.Periods;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.Timelaps;
+import org.openhab.core.i18n.TimeZoneProvider;
+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.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * The {@link MeteoFranceDeserializer} is responsible to instantiate suitable Gson (de)serializer
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+@Component(service = MeteoFranceDeserializer.class)
+public class MeteoFranceDeserializer {
+ private final Gson gson;
+
+ @Activate
+ public MeteoFranceDeserializer(final @Reference TimeZoneProvider timeZoneProvider) {
+ gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+ .registerTypeAdapterFactory(new StrictEnumTypeAdapterFactory())
+ .registerTypeAdapter(Periods.class, new PeriodsDeserializer())
+ .registerTypeAdapter(Timelaps.class, new TimelapsDeserializer())
+ .registerTypeAdapter(ZonedDateTime.class,
+ (JsonDeserializer<ZonedDateTime>) (json, type, context) -> ZonedDateTime
+ .parse(json.getAsJsonPrimitive().getAsString())
+ .withZoneSameInstant(timeZoneProvider.getTimeZone()))
+ .create();
+ }
+
+ public <T> T deserialize(Class<T> clazz, String json) throws MeteoFranceException {
+ try {
+ @Nullable
+ T result = gson.fromJson(json, clazz);
+ if (result != null) {
+ return result;
+ }
+ throw new MeteoFranceException("Deserialization of '%s' resulted in null value", json);
+ } catch (JsonSyntaxException e) {
+ throw new MeteoFranceException(e, "Unexpected error deserializing '%s'", json);
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.deserialization;
+
+import java.lang.reflect.Type;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.Period;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.Periods;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+
+/**
+ * The {@link PeriodsDeserializer} is a specialized deserializer aimed to transform
+ * a list of `Period` into a map identified by the Period Term.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+class PeriodsDeserializer implements JsonDeserializer<Periods> {
+ @Override
+ public @NonNull Periods deserialize(JsonElement json, Type clazz, JsonDeserializationContext context)
+ throws JsonParseException {
+ Periods result = new Periods();
+ if (json instanceof JsonArray jsonArray) {
+ jsonArray.forEach(item -> {
+ Period period = context.deserialize(item, Period.class);
+ result.put(period.echeance(), period);
+ });
+ }
+ return result;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.deserialization;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+import com.google.gson.Gson;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * Enforces a fallback to UNKNOWN when deserializing enum types, marked as @NonNull whereas they were valued
+ * to null if the appropriate value is absent.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+class StrictEnumTypeAdapterFactory implements TypeAdapterFactory {
+ private static final StringReader UNKNOWN = new StringReader("\"UNKNOWN\"");
+
+ @Override
+ public @Nullable <T> TypeAdapter<T> create(@NonNullByDefault({}) Gson gson,
+ @NonNullByDefault({}) TypeToken<T> type) {
+ @SuppressWarnings("unchecked")
+ Class<T> rawType = (Class<T>) type.getRawType();
+ return rawType.isEnum() ? newStrictEnumAdapter(gson.getDelegateAdapter(this, type)) : null;
+ }
+
+ private <T> TypeAdapter<T> newStrictEnumAdapter(@NonNullByDefault({}) TypeAdapter<T> delegateAdapter) {
+ return new TypeAdapter<>() {
+ @Override
+ public void write(JsonWriter out, @Nullable T value) throws IOException {
+ delegateAdapter.write(out, value);
+ }
+
+ @Override
+ public @Nullable T read(JsonReader in) throws IOException {
+ JsonReader delegateReader = new JsonReader(new StringReader('"' + in.nextString() + '"'));
+ @Nullable
+ T value = delegateAdapter.read(delegateReader);
+ delegateReader.close();
+ if (value == null) {
+ UNKNOWN.reset();
+ value = delegateAdapter.read(new JsonReader(UNKNOWN));
+ }
+ return value;
+ }
+ };
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.deserialization;
+
+import java.lang.reflect.Type;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.DomainId;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.Timelaps;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+
+/**
+ * The {@link TimelapsDeserializer} is a specialized deserializer aimed to transform
+ * a list of `Period` into a map identified by the Period Term.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+class TimelapsDeserializer implements JsonDeserializer<Timelaps> {
+ @Override
+ public @NonNull Timelaps deserialize(JsonElement json, Type clazz, JsonDeserializationContext context)
+ throws JsonParseException {
+ Timelaps result = new Timelaps();
+ JsonElement domains = json.getAsJsonObject().get("domain_ids");
+ if (domains instanceof JsonArray jsonArray) {
+ jsonArray.forEach(item -> {
+ DomainId domainId = context.deserialize(item, DomainId.class);
+ result.put(domainId.domain(), domainId);
+ });
+ }
+ return result;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.discovery;
+
+import static org.openhab.binding.meteofrance.internal.MeteoFranceBindingConstants.*;
+import static org.openhab.binding.meteofrance.internal.config.ForecastConfiguration.LOCATION;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.meteofrance.internal.config.DepartmentConfiguration;
+import org.openhab.binding.meteofrance.internal.db.DepartmentDbService;
+import org.openhab.binding.meteofrance.internal.db.DepartmentDbService.Department;
+import org.openhab.binding.meteofrance.internal.handler.MeteoFranceBridgeHandler;
+import org.openhab.core.config.discovery.AbstractThingHandlerDiscoveryService;
+import org.openhab.core.config.discovery.DiscoveryResultBuilder;
+import org.openhab.core.i18n.LocaleProvider;
+import org.openhab.core.i18n.LocationProvider;
+import org.openhab.core.i18n.TranslationProvider;
+import org.openhab.core.library.types.PointType;
+import org.openhab.core.thing.ThingUID;
+import org.openhab.core.thing.binding.ThingHandlerService;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link MeteoFranceDiscoveryService} discovers departments on the configured location.
+ *
+ * @author Gaël L'hopital - Initial Contribution
+ */
+@Component(service = ThingHandlerService.class)
+@NonNullByDefault
+public class MeteoFranceDiscoveryService extends AbstractThingHandlerDiscoveryService<MeteoFranceBridgeHandler> {
+ private static final int DISCOVER_TIMEOUT_SECONDS = 2;
+ private @NonNullByDefault({}) LocationProvider locationProvider;
+ private @NonNullByDefault({}) DepartmentDbService dbService;
+
+ private final Logger logger = LoggerFactory.getLogger(MeteoFranceDiscoveryService.class);
+
+ public MeteoFranceDiscoveryService() {
+ super(MeteoFranceBridgeHandler.class, DISCOVERABLE_THING_TYPES_UIDS, DISCOVER_TIMEOUT_SECONDS);
+ }
+
+ @Reference(unbind = "-")
+ public void bindTranslationProvider(TranslationProvider translationProvider) {
+ this.i18nProvider = translationProvider;
+ }
+
+ @Reference(unbind = "-")
+ public void bindLocaleProvider(LocaleProvider localeProvider) {
+ this.localeProvider = localeProvider;
+ }
+
+ @Reference(unbind = "-")
+ public void bindLocationProvider(LocationProvider locationProvider) {
+ this.locationProvider = locationProvider;
+ }
+
+ @Reference(unbind = "-")
+ public void bindDepartmentDbService(DepartmentDbService dbService) {
+ this.dbService = dbService;
+ }
+
+ @Override
+ public void startScan() {
+ logger.debug("Starting Meteo France department discovery scan");
+
+ LocationProvider localLocation = locationProvider;
+ PointType location = localLocation != null ? localLocation.getLocation() : null;
+ if (location == null) {
+ logger.debug("LocationProvider.getLocation() is not set -> Will not provide any discovery results");
+ return;
+ }
+
+ createDepartmentResults(location);
+ createForecastResults(location);
+ }
+
+ private void createForecastResults(PointType location) {
+ thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_RAIN_FORECAST, LOCAL))
+ .withLabel("@text/discovery.meteofrance.rain-forecast.local.label")
+ .withProperty(LOCATION, location.toString()).withRepresentationProperty(LOCATION).build());
+ }
+
+ private void createDepartmentResults(PointType serverLocation) {
+ List<Department> candidates = dbService.getBounding(serverLocation);
+ ThingUID bridgeUID = thingHandler.getThing().getUID();
+ if (!candidates.isEmpty()) {
+ candidates.forEach(dep -> thingDiscovered(
+ DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_VIGILANCE, bridgeUID, dep.id()))//
+ .withLabel("Vigilance Météo: %s".formatted(dep.name())) //
+ .withProperty(DepartmentConfiguration.DEPARTMENT, dep.id()) //
+ .withRepresentationProperty(DepartmentConfiguration.DEPARTMENT) //
+ .withBridge(bridgeUID).build()));
+ } else {
+ logger.info("No department could be discovered matching server location");
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public enum BlocType {
+ SITUATION, // Situation Actuelle
+ INCERTITUDE, // Prévisibilité et incertitudes
+ QUALIFICATION, // Qualification
+ EVOLUTION, // Évolution prévue
+ UNKNOWN // Inconnue
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.dto;
+
+import java.lang.reflect.Field;
+import java.util.EnumSet;
+import java.util.Objects;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public enum Domain {
+ @SerializedName("FRA")
+ FRANCE("France"),
+
+ @SerializedName("ZDF_EST")
+ ZDF_EST("Défense Est"),
+ @SerializedName("ZDF_PARIS")
+ ZDF_PARIS("Défense Paris"),
+ @SerializedName("ZDF_NORD")
+ ZDF_NORD("Défense Nord"),
+ @SerializedName("ZDF_SUD_EST")
+ ZDF_SUD_EST("Défense Sud-Est"),
+ @SerializedName("ZDF_SUD_OUEST")
+ ZDF_SUD_OUEST("Défense Sud-Ouest"),
+ @SerializedName("ZDF_SUD")
+ ZDF_SUD("Défense Sud"),
+ @SerializedName("ZDF_OUEST")
+ ZDF_OUEST("Défense Ouest"),
+
+ @SerializedName("01")
+ AIN("Ain"),
+ @SerializedName("02")
+ AISNE("Aisne"),
+ @SerializedName("03")
+ ALLIER("Allier"),
+ @SerializedName("04")
+ ALPES_DE_HAUTE_PROVENCE("Alpes-de-Haute-Provence"),
+ @SerializedName("05")
+ HAUTES_ALPES("Hautes-Alpes"),
+ @SerializedName("06")
+ ALPES_MARITIMES("Alpes-Maritimes"),
+ @SerializedName("07")
+ ARDECHE("Ardèche"),
+ @SerializedName("08")
+ ARDENNES("Ardennes"),
+ @SerializedName("09")
+ ARIEGE("Ariège"),
+ @SerializedName("10")
+ AUBE("Aube"),
+ @SerializedName("11")
+ AUDE("Aude"),
+ @SerializedName("12")
+ AVEYRON("Aveyron"),
+ @SerializedName("13")
+ BOUCHES_DU_RHONE("Bouches-du-Rhône"),
+ @SerializedName("14")
+ CALVADOS("Calvados"),
+ @SerializedName("15")
+ CANTAL("Cantal"),
+ @SerializedName("16")
+ CHARENTE("Charente"),
+ @SerializedName("17")
+ CHARENTE_MARITIME("Charente-Maritime"),
+ @SerializedName("18")
+ CHER("Cher"),
+ @SerializedName("19")
+ CORREZE("Corrèze"),
+ @SerializedName("2A")
+ CORSE_DU_SUD("Corse-du-Sud"),
+ @SerializedName("2B")
+ HAUTE_CORSE("Haute-Corse"),
+ @SerializedName("21")
+ COTE_D_OR("Côte-d'Or"),
+ @SerializedName("22")
+ COTES_D_ARMOR("Côtes-d'Armor"),
+ @SerializedName("23")
+ CREUSE("Creuse"),
+ @SerializedName("24")
+ DORDOGNE("Dordogne"),
+ @SerializedName("25")
+ DOUBS("Doubs"),
+ @SerializedName("26")
+ DROME("Drôme"),
+ @SerializedName("27")
+ EURE("Eure"),
+ @SerializedName("28")
+ EURE_ET_LOIR("Eure-et-Loir"),
+ @SerializedName("29")
+ FINISTERE("Finistère"),
+ @SerializedName("30")
+ GARD("Gard"),
+ @SerializedName("31")
+ HAUTE_GARONNE("Haute-Garonne"),
+ @SerializedName("32")
+ GERS("Gers"),
+ @SerializedName("33")
+ GIRONDE("Gironde"),
+ @SerializedName("34")
+ HERAULT("Hérault"),
+ @SerializedName("35")
+ ILLE_ET_VILAINE("Ille-et-Vilaine"),
+ @SerializedName("36")
+ INDRE("Indre"),
+ @SerializedName("37")
+ INDRE_ET_LOIRE("Indre-et-Loire"),
+ @SerializedName("38")
+ ISERE("Isère"),
+ @SerializedName("39")
+ JURA("Jura"),
+ @SerializedName("40")
+ LANDES("Landes"),
+ @SerializedName("41")
+ LOIR_ET_CHER("Loir-et-Cher"),
+ @SerializedName("42")
+ LOIRE("Loire"),
+ @SerializedName("43")
+ HAUTE_LOIRE("Haute-Loire"),
+ @SerializedName("44")
+ LOIRE_ATLANTIQUE("Loire-Atlantique"),
+ @SerializedName("45")
+ LOIRET("Loiret"),
+ @SerializedName("46")
+ LOT("Lot"),
+ @SerializedName("47")
+ LOT_ET_GARONNE("Lot-et-Garonne"),
+ @SerializedName("48")
+ LOZERE("Lozère"),
+ @SerializedName("49")
+ MAINE_ET_LOIRE("Maine-et-Loire"),
+ @SerializedName("50")
+ MANCHE("Manche"),
+ @SerializedName("51")
+ MARNE("Marne"),
+ @SerializedName("52")
+ HAUTE_MARNE("Haute-Marne"),
+ @SerializedName("53")
+ MAYENNE("Mayenne"),
+ @SerializedName("54")
+ MEURTHE_ET_MOSELLE("Meurthe-et-Moselle"),
+ @SerializedName("55")
+ MEUSE("Meuse"),
+ @SerializedName("56")
+ MORBIHAN("Morbihan"),
+ @SerializedName("57")
+ MOSELLE("Moselle"),
+ @SerializedName("58")
+ NIEVRE("Nièvre"),
+ @SerializedName("59")
+ NORD("Nord"),
+ @SerializedName("60")
+ OISE("Oise"),
+ @SerializedName("61")
+ ORNE("Orne"),
+ @SerializedName("62")
+ PAS_DE_CALAIS("Pas-de-Calais"),
+ @SerializedName("63")
+ PUY_DE_DOME("Puy-de-Dôme"),
+ @SerializedName("64")
+ PYRENEES_ATLANTIQUES("Pyrénées-Atlantiques"),
+ @SerializedName("65")
+ HAUTES_PYRENEES("Hautes-Pyrénées"),
+ @SerializedName("66")
+ PYRENEES_ORIENTALES("Pyrénées-Orientales"),
+ @SerializedName("67")
+ BAS_RHIN("Bas-Rhin"),
+ @SerializedName("68")
+ HAUT_RHIN("Haut-Rhin"),
+ @SerializedName("69")
+ RHONE("Rhône"),
+ @SerializedName("70")
+ HAUTE_SAONE("Haute-Saône"),
+ @SerializedName("71")
+ SAONE_ET_LOIRE("Saône-et-Loire"),
+ @SerializedName("72")
+ SARTHE("Sarthe"),
+ @SerializedName("73")
+ SAVOIE("Savoie"),
+ @SerializedName("74")
+ HAUTE_SAVOIE("Haute-Savoie"),
+ @SerializedName("75")
+ PARIS("Paris"),
+ @SerializedName("76")
+ SEINE_MARITIME("Seine-Maritime"),
+ @SerializedName("77")
+ SEINE_ET_MARNE("Seine-et-Marne"),
+ @SerializedName("78")
+ YVELINES("Yvelines"),
+ @SerializedName("79")
+ DEUX_SEVRES("Deux-Sèvres"),
+ @SerializedName("80")
+ SOMME("Somme"),
+ @SerializedName("81")
+ TARN("Tarn"),
+ @SerializedName("82")
+ TARN_ET_GARONNE("Tarn-et-Garonne"),
+ @SerializedName("83")
+ VAR("Var"),
+ @SerializedName("84")
+ VAUCLUSE("Vaucluse"),
+ @SerializedName("85")
+ VENDEE("Vendée"),
+ @SerializedName("86")
+ VIENNE("Vienne"),
+ @SerializedName("87")
+ HAUTE_VIENNE("Haute-Vienne"),
+ @SerializedName("88")
+ VOSGES("Vosges"),
+ @SerializedName("89")
+ YONNE("Yonne"),
+ @SerializedName("90")
+ TERRITOIRE_DE_BELFORT("Territoire de Belfort"),
+ @SerializedName("91")
+ ESSONNE("Essonne"),
+ @SerializedName("92")
+ HAUTS_DE_SEINE("Hauts-de-Seine"),
+ @SerializedName("93")
+ SEINE_SAINT_DENIS("Seine-Saint-Denis"),
+ @SerializedName("94")
+ VAL_DE_MARNE("Val-de-Marne"),
+ @SerializedName("95")
+ VAL_D_OISE("Val-d'Oise"),
+ @SerializedName("99")
+ ANDORRE("Andorre"),
+
+ UNKNOWN("Unknown");
+
+ public final String description;
+ private final @Nullable String apiId;
+
+ Domain(String description) {
+ this.description = description;
+ this.apiId = getSerializedName();
+ }
+
+ @Nullable
+ private String getSerializedName() {
+ try {
+ Field f = getClass().getField(this.name());
+ SerializedName a = f.getAnnotation(SerializedName.class);
+ if (a != null) {
+ return a.value();
+ }
+ } catch (NoSuchFieldException ignored) {
+ }
+ return null;
+ }
+
+ public static Domain getByApiId(String searched) {
+ return Objects.requireNonNull(EnumSet.allOf(Domain.class).stream().filter(dom -> searched.equals(dom.apiId))
+ .findFirst().orElse(UNKNOWN));
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.dto;
+
+import java.util.EnumSet;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public enum Hazard {
+ @SerializedName("1")
+ VENT("vent"),
+ @SerializedName("2")
+ PLUIE("pluie-inondation"),
+ @SerializedName("3")
+ ORAGES("orage"),
+ @SerializedName("4")
+ CRUES("inondation"),
+ @SerializedName("5")
+ NEIGE_VERGLAS("neige"),
+ @SerializedName("6")
+ CANICULE("canicule"),
+ @SerializedName("7")
+ GRAND_FROID("grand-froid"),
+ @SerializedName("8")
+ AVALANCHES("avalanches"),
+ @SerializedName("9")
+ VAGUES_SUBMERSION("vague-submersion"),
+ ALL(""),
+ UNKNOWN("");
+
+ public static final EnumSet<Hazard> AS_SET = EnumSet.allOf(Hazard.class);
+
+ public final String channelName;
+
+ Hazard(String channelName) {
+ this.channelName = channelName;
+ }
+
+ public boolean isChannel() {
+ return !channelName.isEmpty();
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.dto;
+
+import java.time.ZonedDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class MeteoFrance {
+ public record VigilanceEnCours(//
+ @Nullable Product product, //
+ @Nullable Meta meta, //
+ int code, // error code, 0 if all went well
+ @Nullable String message, // error message when code != 0
+ @Nullable String detail) {
+ }
+
+ public record Meta(//
+ String snapshotId, // identifiant du snapshot de la saisie validée
+ ZonedDateTime productDatetime, // date/heure de diffusion du produit
+ ZonedDateTime generationTimestamp) { // date/heure de début de validité du produit
+ }
+
+ public record Product(//
+ String warningType, // "vigilance" - produit de la famille Vigilance
+ String typeCdp, // "cdp_textes" - nom générique du produit
+ String versionVigilance, // "V6" - Version du système développé
+ String versionCdp, // "x.y.z" - version du format pour pouvoir gérer d'anciens jeux de données
+ ZonedDateTime updateTime, // "AAAA-MM-JJThh:mm:ssZ" - date/heure de diffusion du produit
+ @SerializedName("domain_id") Domain domain, //
+ @Nullable List<TextBlocItem> textBlocItems, // contenu textuel des bulletins
+ Periods periods) { // périodes concernées par la Vigilance
+
+ public Optional<TextBlocItem> getBlocItem(Domain searched) {
+ return textBlocItems != null ? textBlocItems.stream().filter(ti -> ti.validFor(searched)).findFirst()
+ : Optional.empty();
+ }
+
+ public Optional<Period> getPeriod(Term term) {
+ return Optional.ofNullable(periods.get(term));
+ }
+ }
+
+ public static class Periods extends HashMap<Term, @Nullable Period> {
+ private static final long serialVersionUID = -4448877461442293135L;
+ }
+
+ public static class Timelaps extends HashMap<Domain, @Nullable DomainId> {
+ private static final long serialVersionUID = -441522278695388073L;
+ }
+
+ public record TextBlocItem( //
+ @SerializedName("domain_id") Domain domain, // code du domaine sur lequel s'applique le bloc textuel
+ String blocTitle, //
+ String blocId, // indique le type de bloc
+ List<BlocItem> blocItems) { // rubriques du bulletin : SITUATION,QUALIFICATION, INCERTITUDE,EVOLUTION
+
+ private boolean validFor(Domain searched) {
+ return searched.equals(domain);
+ }
+ }
+
+ public record Period( //
+ Term echeance, //
+ ZonedDateTime beginValidityTime, //
+ ZonedDateTime endValidityTime, //
+ TextItems textItems, //
+ Timelaps timelaps, //
+ List<PhenomenonCount> maxCountItems, //
+ List<PerPhenomenonItem> perPhenomenonItems) {//
+ }
+
+ private record TextItems( //
+ String title, //
+ List<String> text) {//
+ }
+
+ public record DomainId( //
+ @SerializedName("domain_id") Domain domain, //
+ int maxColorId, //
+ List<PhenomenonItem> phenomenonItems) { //
+ }
+
+ public record PhenomenonItem( //
+ Hazard phenomenonId, //
+ Risk phenomenonMaxColorId, //
+ List<TimelapsItem> timelapsItems) { //
+ }
+
+ public record TimelapsItem( //
+ ZonedDateTime beginTime, //
+ ZonedDateTime endTime, //
+ Risk colorId) { //
+
+ public boolean contains(ZonedDateTime moment) {
+ return beginTime.isBefore(moment) && endTime.isAfter(moment);
+ }
+ }
+
+ private record PhenomenonCount(// )
+ int colorId, //
+ String colorName, //
+ int count, //
+ String textCount) { //
+ }
+
+ private record PerPhenomenonItem( //
+ String phenomenonId, //
+ int anyColorCount, //
+ List<PhenomenonCount> phenomenonCounts) { //
+ }
+
+ public record BlocItem( //
+ String id, // identifiant de la rubrique texte
+ @SerializedName("type_group") BlocType type, // code du groupe de la rubrique
+ List<TextItem> textItems) { // textes à associer à la carte comme les commentaires
+ }
+
+ public record TextItem( //
+ @Nullable String hazardCode, // code du phénomène
+ String typeCode, // code de l'élément de suivi
+ List<TermItem> termItems) {// tableau des éléments de suivi par échéance : J, J1 ou J+J1
+
+ public Hazard getHazard() {
+ return hazardCode == null ? Hazard.ALL : Hazard.valueOf(Objects.requireNonNull(hazardCode));
+ }
+ }
+
+ public record TermItem(//
+ @SerializedName("term_names") Term term, // code de l'échéance
+ @SerializedName("risk_code") Risk risk, // code du risque
+ ZonedDateTime startTime, // date/heure début d'échéance
+ ZonedDateTime endTime, // date/heure fin d'échéance
+ List<SubdivisionText> subdivisionText) {// sous_textes de même type d'éléments de suivi
+
+ public String getText(ZonedDateTime moment) {
+ return startTime.isBefore(moment) && endTime.isAfter(moment) ? subdivisionText.stream()
+ .map(SubdivisionText::getText).collect(Collectors.joining(System.lineSeparator())) : "";
+ }
+ }
+
+ private record SubdivisionText( //
+ String underlineText, // texte devant être souligné dans le bulletin
+ List<String> text) { // contenu du texte ligne par ligne
+
+ String getText() {
+ return (underlineText.isEmpty() ? "" : underlineText + System.lineSeparator()) + text.stream()
+ .filter(Predicate.not(String::isEmpty)).collect(Collectors.joining(System.lineSeparator()));
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.dto;
+
+import java.time.ZonedDateTime;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class RainForecast {
+ public enum RainIntensity {
+ @SerializedName("1")
+ TEMPS_SEC,
+ @SerializedName("2")
+ FAIBLE,
+ @SerializedName("3")
+ MODEREE,
+ @SerializedName("4")
+ FORTE,
+ UNKNOWN;
+ }
+
+ public record Forecast(ZonedDateTime time, RainIntensity rainIntensity, String rainIntensityDescription) {
+ }
+
+ public record Geometry(String type, List<Double> coordinates) {
+ }
+
+ public class Properties {
+ public int altitude;
+ public String name = "";
+ public String country = "";
+ public String frenchDepartment = "";
+ public int rainProductAvailable;
+ public String timezone = "";
+ public int confidence;
+ public List<Forecast> forecast = List.of();
+ }
+
+ public @Nullable ZonedDateTime updateTime;
+ public String type = "";
+ public @Nullable Geometry geometry;
+ public @Nullable Properties properties;
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public enum Risk {
+ @SerializedName("1")
+ VERT("#15ed13", 0),
+ @SerializedName("2")
+ JAUNE("#f9ff00", 1),
+ @SerializedName("3")
+ ORANGE("#f7a401", 2),
+ @SerializedName("4")
+ ROUGE("#e71919", 3),
+ UNKNOWN("#000000", -1);
+
+ public final String rgbColor;
+ public final int riskLevel;
+
+ Risk(String rgbColor, int riskLevel) {
+ this.rgbColor = rgbColor;
+ this.riskLevel = riskLevel;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public enum Term {
+ @SerializedName("J")
+ TODAY,
+ @SerializedName("J1")
+ TOMORROW,
+ @SerializedName("J+J1")
+ TODAY_AND_TOMORROW,
+ UNKNOWN
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.handler;
+
+import static org.openhab.binding.meteofrance.internal.MeteoFranceBindingConstants.REQUEST_TIMEOUT_MS;
+
+import java.io.IOException;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.HttpMethod;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.meteofrance.internal.MeteoFranceException;
+import org.openhab.binding.meteofrance.internal.config.BridgeConfiguration;
+import org.openhab.binding.meteofrance.internal.deserialization.MeteoFranceDeserializer;
+import org.openhab.binding.meteofrance.internal.dto.Domain;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.DomainId;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.Meta;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.Period;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.Product;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.TextBlocItem;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.VigilanceEnCours;
+import org.openhab.binding.meteofrance.internal.dto.RainForecast;
+import org.openhab.binding.meteofrance.internal.dto.Term;
+import org.openhab.core.cache.ExpiringCache;
+import org.openhab.core.io.net.http.HttpUtil;
+import org.openhab.core.library.types.PointType;
+import org.openhab.core.thing.Bridge;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.ThingStatus;
+import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.binding.BaseBridgeHandler;
+import org.openhab.core.types.Command;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link MeteoFranceBridgeHandler} is the handler for Meteo France bridge and connects it
+ * to the Meteo France API Portal
+ *
+ * @author Gaël L'hopital - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class MeteoFranceBridgeHandler extends BaseBridgeHandler {
+ private static final String PORTAIL_API_BASE_URL = "https://public-api.meteofrance.fr/public/DPVigilance/v1/%s/encours";
+ private static final String TEXTE_VIGILANCE_URL = PORTAIL_API_BASE_URL.formatted("textesvigilance");
+ private static final String CARTE_VIGILANCE_URL = PORTAIL_API_BASE_URL.formatted("cartevigilance");
+
+ private static final String RAIN_FORECAST_BASE_URL = "https://rpcache-aa.meteofrance.com/internet2018client/2.0/nowcast/rain?lat=%.4f&lon=%.4f&token=__Wj7dVSTjV9YGu1guveLyDq0g7S7TfTjaHBTPTpO0kj8__";
+
+ private static final long CACHE_EXPIRY = TimeUnit.MINUTES.toMillis(10);
+
+ private final Logger logger = LoggerFactory.getLogger(MeteoFranceBridgeHandler.class);
+ private final Properties header = new Properties();
+ private final MeteoFranceDeserializer deserializer;
+
+ private final ExpiringCache<VigilanceEnCours> vigilanceText;
+ private final ExpiringCache<VigilanceEnCours> vigilanceMap;
+
+ public MeteoFranceBridgeHandler(Bridge bridge, MeteoFranceDeserializer deserializer) {
+ super(bridge);
+ this.deserializer = deserializer;
+
+ vigilanceText = new ExpiringCache<>(CACHE_EXPIRY, () -> this.getVigilanceEnCours(TEXTE_VIGILANCE_URL));
+ vigilanceMap = new ExpiringCache<>(CACHE_EXPIRY, () -> this.getVigilanceEnCours(CARTE_VIGILANCE_URL));
+ }
+
+ @Override
+ public void initialize() {
+ logger.debug("Initializing Meteo-France API bridge handler.");
+ BridgeConfiguration config = getConfigAs(BridgeConfiguration.class);
+ if (config.apikey.isEmpty()) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+ "@text/offline.config-error-unknown-apikey");
+ return;
+ }
+ header.put("apikey", config.apikey);
+ header.put("accept", "*/*");
+ updateStatus(ThingStatus.UNKNOWN);
+ scheduler.execute(() -> vigilanceText.getValue());
+ }
+
+ @Override
+ public void dispose() {
+ header.clear();
+ }
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ // The bridge does not handle commands
+ }
+
+ private @Nullable VigilanceEnCours getVigilanceEnCours(String url) {
+ try {
+ String answer = HttpUtil.executeUrl(HttpMethod.GET, url, header, null, null, REQUEST_TIMEOUT_MS);
+ logger.trace(answer);
+
+ VigilanceEnCours vigilance = deserializer.deserialize(MeteoFrance.VigilanceEnCours.class, answer);
+ if (vigilance.code() != 0) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, vigilance.message());
+ } else {
+ updateStatus(ThingStatus.ONLINE);
+ return vigilance;
+ }
+ } catch (MeteoFranceException e) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+ "Exception deserializing API answer: %s".formatted(e.getMessage()));
+ } catch (IOException e) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
+ }
+ return null;
+ }
+
+ public @Nullable TextBlocItem requestTextData(Domain domain) {
+ VigilanceEnCours local = vigilanceText.getValue();
+ if (local != null) {
+ Product product = local.product();
+ if (product != null) {
+ return product.getBlocItem(domain).get();
+ }
+ }
+ return null;
+ }
+
+ public @Nullable DomainId requestMapData(Domain domain, Term term) {
+ Period period = requestPeriod(term);
+ return period != null ? period.timelaps().get(domain) : null;
+ }
+
+ public @Nullable Period requestPeriod(Term term) {
+ VigilanceEnCours local = vigilanceMap.getValue();
+ if (local != null) {
+ Product product = local.product();
+ if (product != null) {
+ return product.getPeriod(term).get();
+ }
+ }
+ return null;
+ }
+
+ public Optional<Meta> getMeta() {
+ VigilanceEnCours local = vigilanceText.getValue();
+ return Optional.ofNullable(local != null ? local.meta() : null);
+ }
+
+ public @Nullable RainForecast getRainForecast(PointType location) {
+ String url = RAIN_FORECAST_BASE_URL.formatted(location.getLatitude().doubleValue(),
+ location.getLongitude().doubleValue());
+ try {
+ String answer = HttpUtil.executeUrl(HttpMethod.GET, url, REQUEST_TIMEOUT_MS);
+ return deserializer.deserialize(RainForecast.class, answer);
+ } catch (MeteoFranceException e) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+ "Exception deserializing API answer: %s".formatted(e.getMessage()));
+ } catch (IOException e) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
+ }
+ return null;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.handler;
+
+import java.util.Optional;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.thing.Bridge;
+
+/**
+ * {@link MeteoFranceChildHandler} is a common interface for Things having a
+ * {@link MeteoFranceBridgeHandler} Bridge
+ *
+ * @author Gaël L'hopital - Initial contribution
+ *
+ */
+@NonNullByDefault
+public interface MeteoFranceChildHandler {
+ default Optional<MeteoFranceBridgeHandler> getBridgeHandler() {
+ Bridge bridge = getBridge();
+ if (bridge != null) {
+ if (bridge.getHandler() instanceof MeteoFranceBridgeHandler maHandler) {
+ return Optional.of(maHandler);
+ }
+ }
+ return Optional.empty();
+ }
+
+ @Nullable
+ Bridge getBridge();
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.handler;
+
+import static org.openhab.binding.meteofrance.internal.MeteoFranceBindingConstants.*;
+import static org.openhab.core.types.TimeSeries.Policy.REPLACE;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.meteofrance.internal.config.ForecastConfiguration;
+import org.openhab.binding.meteofrance.internal.dto.RainForecast;
+import org.openhab.binding.meteofrance.internal.dto.RainForecast.Forecast;
+import org.openhab.binding.meteofrance.internal.dto.RainForecast.Properties;
+import org.openhab.binding.meteofrance.internal.dto.RainForecast.RainIntensity;
+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.thing.Bridge;
+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.types.Command;
+import org.openhab.core.types.RefreshType;
+import org.openhab.core.types.State;
+import org.openhab.core.types.TimeSeries;
+import org.openhab.core.types.UnDefType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link RainForecastHandler} is responsible for updating channels
+ * and querying the API
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class RainForecastHandler extends BaseThingHandler implements MeteoFranceChildHandler {
+ private final Logger logger = LoggerFactory.getLogger(RainForecastHandler.class);
+ private final ChannelUID intensityChannelUID;
+ private final ZoneId systemZoneId;
+
+ private Optional<ScheduledFuture<?>> refreshJob = Optional.empty();
+ private Optional<PointType> location = Optional.empty();
+
+ public RainForecastHandler(Thing thing, ZoneId zoneId) {
+ super(thing);
+ this.intensityChannelUID = new ChannelUID(getThing().getUID(), INTENSITY);
+ this.systemZoneId = zoneId;
+ }
+
+ @Override
+ public @Nullable Bridge getBridge() {
+ return super.getBridge();
+ }
+
+ @Override
+ public void initialize() {
+ logger.debug("Initializing Rain Forecast handler.");
+ disposeJob();
+
+ updateStatus(ThingStatus.UNKNOWN);
+
+ ForecastConfiguration config = getConfigAs(ForecastConfiguration.class);
+
+ try {
+ this.location = Optional.of(new PointType(config.location));
+ } catch (IllegalArgumentException e) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Incorrect 'location' value.");
+ return;
+ }
+
+ this.refreshJob = Optional.of(scheduler.schedule(this::updateAndPublish, 2, TimeUnit.SECONDS));
+ }
+
+ private void disposeJob() {
+ refreshJob.ifPresent(job -> job.cancel(true));
+ refreshJob = Optional.empty();
+ }
+
+ @Override
+ public void dispose() {
+ logger.debug("Disposing the Rain Forecast handler.");
+ disposeJob();
+ }
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ if (command instanceof RefreshType) {
+ updateAndPublish();
+ }
+ }
+
+ private void updateAndPublish() {
+ getBridgeHandler().ifPresentOrElse(handler -> {
+ location.ifPresent(loc -> {
+ RainForecast forecast = handler.getRainForecast(loc);
+ if (forecast != null) {
+ setProperties(forecast.properties);
+ updateDate(UPDATE_TIME, forecast.updateTime);
+ updateStatus(ThingStatus.ONLINE);
+ }
+ });
+ }, () -> logger.warn("No viable bridge"));
+ }
+
+ private void setProperties(@Nullable Properties forecastProps) {
+ if (forecastProps == null) {
+ return;
+ }
+ Map<String, String> properties = editProperties();
+ properties.put("altitude", "%d m".formatted(forecastProps.altitude));
+ properties.put("name", forecastProps.name);
+ properties.put("country", forecastProps.country);
+ properties.put("department", forecastProps.frenchDepartment);
+ properties.put("timezone", forecastProps.timezone);
+ properties.put("comfidence", "%d".formatted(forecastProps.confidence));
+ this.updateProperties(properties);
+
+ setForecast(forecastProps.forecast);
+ }
+
+ private void setForecast(List<Forecast> forecast) {
+ TimeSeries timeSeries = new TimeSeries(REPLACE);
+
+ forecast.forEach(prevision -> {
+ State state = prevision.rainIntensity() != RainIntensity.UNKNOWN
+ ? new DecimalType(prevision.rainIntensity().ordinal())
+ : UnDefType.UNDEF;
+ timeSeries.add(prevision.time().toInstant(), state);
+ });
+ sendTimeSeries(intensityChannelUID, timeSeries);
+
+ Forecast current = forecast.get(0);
+ long until = ZonedDateTime.now().until(current.time(), ChronoUnit.SECONDS);
+ logger.debug("Refresh rain intensity forecast in : {}s", until);
+ refreshJob = Optional.of(scheduler.schedule(this::updateAndPublish, until, TimeUnit.SECONDS));
+ }
+
+ private void updateDate(String channelId, @Nullable ZonedDateTime zonedDateTime) {
+ if (isLinked(channelId)) {
+ updateState(channelId,
+ zonedDateTime != null ? new DateTimeType(zonedDateTime.withZoneSameInstant(systemZoneId))
+ : UnDefType.NULL);
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 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.meteofrance.internal.handler;
+
+import static org.openhab.binding.meteofrance.internal.MeteoFranceBindingConstants.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.meteofrance.internal.MeteoFranceIconProvider;
+import org.openhab.binding.meteofrance.internal.config.DepartmentConfiguration;
+import org.openhab.binding.meteofrance.internal.dto.BlocType;
+import org.openhab.binding.meteofrance.internal.dto.Domain;
+import org.openhab.binding.meteofrance.internal.dto.Hazard;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.DomainId;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.Period;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.TextBlocItem;
+import org.openhab.binding.meteofrance.internal.dto.MeteoFrance.TimelapsItem;
+import org.openhab.binding.meteofrance.internal.dto.Risk;
+import org.openhab.binding.meteofrance.internal.dto.Term;
+import org.openhab.core.library.types.DateTimeType;
+import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.RawType;
+import org.openhab.core.library.types.StringType;
+import org.openhab.core.thing.Bridge;
+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.types.Command;
+import org.openhab.core.types.RefreshType;
+import org.openhab.core.types.State;
+import org.openhab.core.types.UnDefType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link VigilanceHandler} is responsible for updating channels
+ * and querying the API
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class VigilanceHandler extends BaseThingHandler implements MeteoFranceChildHandler {
+ private final Logger logger = LoggerFactory.getLogger(VigilanceHandler.class);
+ private final MeteoFranceIconProvider iconProvider;
+ private final ZoneId systemZoneId;
+
+ private Optional<ScheduledFuture<?>> refreshJob = Optional.empty();
+
+ private @NonNullByDefault({}) Domain domain;
+
+ public VigilanceHandler(Thing thing, ZoneId zoneId, MeteoFranceIconProvider iconProvider) {
+ super(thing);
+ this.iconProvider = iconProvider;
+ this.systemZoneId = zoneId;
+ }
+
+ @Override
+ public @Nullable Bridge getBridge() {
+ return super.getBridge();
+ }
+
+ @Override
+ public void initialize() {
+ logger.debug("Initializing Vigilance Météo handler.");
+ disposeJob();
+
+ DepartmentConfiguration config = getConfigAs(DepartmentConfiguration.class);
+
+ domain = Domain.getByApiId(config.department);
+ if (Domain.UNKNOWN.equals(domain)) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+ "Wrong department: %s".formatted((config.department)));
+ return;
+ }
+ logger.debug("config department= {}", config.department);
+
+ updateStatus(ThingStatus.UNKNOWN);
+ refreshJob = Optional
+ .of(scheduler.scheduleWithFixedDelay(this::updateAndPublish, 5, config.refresh * 60, TimeUnit.SECONDS));
+ }
+
+ private void disposeJob() {
+ refreshJob.ifPresent(job -> job.cancel(true));
+ refreshJob = Optional.empty();
+ }
+
+ @Override
+ public void dispose() {
+ logger.debug("Disposing the Vigilance Météo handler.");
+ disposeJob();
+ }
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ if (command instanceof RefreshType) {
+ updateAndPublish();
+ }
+ }
+
+ private void updateAndPublish() {
+ getBridgeHandler().ifPresentOrElse(handler -> {
+ Period period = handler.requestPeriod(Term.TODAY);
+ if (period != null) {
+ updateDate(OBSERVATION_TIME, period.beginValidityTime());
+ updateDate(END_TIME, period.endValidityTime());
+ }
+ DomainId domainId = handler.requestMapData(domain, Term.TODAY);
+ ZonedDateTime now = ZonedDateTime.now().withZoneSameInstant(systemZoneId);
+ if (domainId != null) {
+ Map<Hazard, Risk> channels = new HashMap<>(Hazard.values().length);
+ Hazard.AS_SET.stream().filter(Hazard::isChannel).forEach(hazard -> channels.put(hazard, Risk.VERT));
+
+ domainId.phenomenonItems().forEach(phenomenon -> {
+ Risk risk = phenomenon.phenomenonMaxColorId();
+ for (TimelapsItem item : phenomenon.timelapsItems()) {
+ if (item.contains(now)) {
+ risk = item.colorId();
+ }
+ }
+ channels.put(phenomenon.phenomenonId(), risk);
+ });
+
+ channels.forEach((k, v) -> updateAlert(k.channelName, v));
+
+ TextBlocItem bloc = handler.requestTextData(domain);
+ if (bloc != null) {
+ String comment = bloc.blocItems().stream().filter(bi -> bi.type().equals(BlocType.SITUATION))
+ .flatMap(bi -> bi.textItems().stream()).flatMap(ti -> ti.termItems().stream())
+ .map(term -> term.getText(now)).collect(Collectors.joining("."));
+ updateState(COMMENT, comment.isEmpty() ? UnDefType.NULL : StringType.valueOf(comment));
+ }
+ updateStatus(ThingStatus.ONLINE);
+ } else {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "No data available for the department");
+ }
+ }, () -> logger.warn("No viable bridge"));
+ }
+
+ private void updateAlert(String channelId, Risk value) {
+ State state = value != Risk.UNKNOWN ? new DecimalType(value.riskLevel) : UnDefType.NULL;
+ if (isLinked(channelId)) {
+ updateState(channelId, state);
+ }
+
+ String channelIcon = channelId + "-icon";
+ if (isLinked(channelIcon)) {
+ InputStream icon = iconProvider.getIcon(channelId, state.toString());
+ if (icon != null) {
+ try {
+ State result = new RawType(icon.readAllBytes(), "image/svg+xml");
+ updateState(channelIcon, result);
+ } catch (IOException e) {
+ logger.warn("Error getting icon for channel {} and value {}: {}", channelId, value, e.getMessage());
+ }
+ } else {
+ logger.warn("Null icon returned for channel {} and state {}", channelIcon, state);
+ }
+ }
+ }
+
+ private void updateDate(String channelId, ZonedDateTime zonedDateTime) {
+ if (isLinked(channelId)) {
+ updateState(channelId, new DateTimeType(zonedDateTime.withZoneSameInstant(systemZoneId)));
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<addon:addon id="meteofrance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
+ xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
+
+ <type>binding</type>
+ <name>Météo France Binding</name>
+ <description>Retrieves various weather information from Météo France APIs</description>
+ <connection>cloud</connection>
+ <countries>fr</countries>
+
+</addon:addon>
--- /dev/null
+# add-on
+
+addon.meteofrance.name = Météo France Binding
+addon.meteofrance.description = Retrieves various weather information from Météo France APIs
+
+# thing types
+
+thing-type.meteofrance.api.label = Météo-France API Portal
+thing-type.meteofrance.api.description = Bridge to the Météo-France API Portal. In order to receive the data, you must register an account on https://portail-api.meteofrance.fr/devportal/apis and get your API token.
+thing-type.meteofrance.rain-forecast.label = Precipitation Forecast
+thing-type.meteofrance.rain-forecast.description = Provides precipitation forecast for the next hour
+thing-type.meteofrance.vigilance.label = Department Awareness
+thing-type.meteofrance.vigilance.description = Provides weather alert levels for a department.
+thing-type.meteofrance.vigilance.channel.avalanches-icon.label = Avalanche Icon
+thing-type.meteofrance.vigilance.channel.canicule-icon.label = Heat Wave Icon
+thing-type.meteofrance.vigilance.channel.end-time.label = End of Validity
+thing-type.meteofrance.vigilance.channel.grand-froid-icon.label = Extreme Cold Icon
+thing-type.meteofrance.vigilance.channel.inondation-icon.label = Flood Icon
+thing-type.meteofrance.vigilance.channel.neige-icon.label = Snow Icon
+thing-type.meteofrance.vigilance.channel.observation-time.label = Start of Validity
+thing-type.meteofrance.vigilance.channel.orage-icon.label = Storm Icon
+thing-type.meteofrance.vigilance.channel.pluie-inondation-icon.label = Rain Flood Icon
+thing-type.meteofrance.vigilance.channel.vague-submersion-icon.label = Wave Submersion Icon
+thing-type.meteofrance.vigilance.channel.vent-icon.label = Wind Icon
+
+# thing types config
+
+thing-type.config.meteofrance.api.apikey.label = API Key
+thing-type.config.meteofrance.api.apikey.description = Data-platform token to access the service
+thing-type.config.meteofrance.rain-forecast.location.label = Location
+thing-type.config.meteofrance.rain-forecast.location.description = Your geo coordinates separated with comma (e.g. "37.8,-122.4,177").
+thing-type.config.meteofrance.vigilance.department.label = Department
+thing-type.config.meteofrance.vigilance.department.description = Name of the department
+thing-type.config.meteofrance.vigilance.department.option.01 = Ain
+thing-type.config.meteofrance.vigilance.department.option.02 = Aisne
+thing-type.config.meteofrance.vigilance.department.option.03 = Allier
+thing-type.config.meteofrance.vigilance.department.option.04 = Alpes de Haute Provence
+thing-type.config.meteofrance.vigilance.department.option.06 = Alpes Maritimes
+thing-type.config.meteofrance.vigilance.department.option.07 = Ardèche
+thing-type.config.meteofrance.vigilance.department.option.08 = Ardennes
+thing-type.config.meteofrance.vigilance.department.option.09 = Ariège
+thing-type.config.meteofrance.vigilance.department.option.10 = Aube
+thing-type.config.meteofrance.vigilance.department.option.11 = Aude
+thing-type.config.meteofrance.vigilance.department.option.12 = Aveyron
+thing-type.config.meteofrance.vigilance.department.option.67 = Bas-Rhin
+thing-type.config.meteofrance.vigilance.department.option.13 = Bouches du Rhône
+thing-type.config.meteofrance.vigilance.department.option.14 = Calvados
+thing-type.config.meteofrance.vigilance.department.option.15 = Cantal
+thing-type.config.meteofrance.vigilance.department.option.16 = Charente
+thing-type.config.meteofrance.vigilance.department.option.17 = Charente Maritime
+thing-type.config.meteofrance.vigilance.department.option.18 = Cher
+thing-type.config.meteofrance.vigilance.department.option.19 = Corrèze
+thing-type.config.meteofrance.vigilance.department.option.2A = Corse du Sud
+thing-type.config.meteofrance.vigilance.department.option.21 = Côte D'Or
+thing-type.config.meteofrance.vigilance.department.option.22 = Côtes D'Armor
+thing-type.config.meteofrance.vigilance.department.option.23 = Creuse
+thing-type.config.meteofrance.vigilance.department.option.79 = Deux Sèvres
+thing-type.config.meteofrance.vigilance.department.option.24 = Dordogne
+thing-type.config.meteofrance.vigilance.department.option.25 = Doubs
+thing-type.config.meteofrance.vigilance.department.option.26 = Drôme
+thing-type.config.meteofrance.vigilance.department.option.91 = Essonne
+thing-type.config.meteofrance.vigilance.department.option.27 = Eure
+thing-type.config.meteofrance.vigilance.department.option.28 = Eure et Loir
+thing-type.config.meteofrance.vigilance.department.option.29 = Finistère
+thing-type.config.meteofrance.vigilance.department.option.30 = Gard
+thing-type.config.meteofrance.vigilance.department.option.32 = Gers
+thing-type.config.meteofrance.vigilance.department.option.33 = Gironde
+thing-type.config.meteofrance.vigilance.department.option.68 = Haut-Rhin
+thing-type.config.meteofrance.vigilance.department.option.2B = Haute Corse
+thing-type.config.meteofrance.vigilance.department.option.31 = Haute Garonne
+thing-type.config.meteofrance.vigilance.department.option.43 = Haute Loire
+thing-type.config.meteofrance.vigilance.department.option.52 = Haute Marne
+thing-type.config.meteofrance.vigilance.department.option.70 = Haute Saône
+thing-type.config.meteofrance.vigilance.department.option.74 = Haute Savoie
+thing-type.config.meteofrance.vigilance.department.option.87 = Haute Vienne
+thing-type.config.meteofrance.vigilance.department.option.05 = Hautes Alpes
+thing-type.config.meteofrance.vigilance.department.option.65 = Hautes Pyrénées
+thing-type.config.meteofrance.vigilance.department.option.92 = Hauts de Seine
+thing-type.config.meteofrance.vigilance.department.option.34 = Hérault
+thing-type.config.meteofrance.vigilance.department.option.35 = Ille et Vilaine
+thing-type.config.meteofrance.vigilance.department.option.36 = Indre
+thing-type.config.meteofrance.vigilance.department.option.37 = Indre et Loire
+thing-type.config.meteofrance.vigilance.department.option.38 = Isère
+thing-type.config.meteofrance.vigilance.department.option.39 = Jura
+thing-type.config.meteofrance.vigilance.department.option.40 = Landes
+thing-type.config.meteofrance.vigilance.department.option.41 = Loir et Cher
+thing-type.config.meteofrance.vigilance.department.option.42 = Loire
+thing-type.config.meteofrance.vigilance.department.option.44 = Loire Atlantique
+thing-type.config.meteofrance.vigilance.department.option.45 = Loiret
+thing-type.config.meteofrance.vigilance.department.option.46 = Lot
+thing-type.config.meteofrance.vigilance.department.option.47 = Lot et Garonne
+thing-type.config.meteofrance.vigilance.department.option.48 = Lozère
+thing-type.config.meteofrance.vigilance.department.option.49 = Maine et Loire
+thing-type.config.meteofrance.vigilance.department.option.50 = Manche
+thing-type.config.meteofrance.vigilance.department.option.51 = Marne
+thing-type.config.meteofrance.vigilance.department.option.53 = Mayenne
+thing-type.config.meteofrance.vigilance.department.option.54 = Meurthe et Moselle
+thing-type.config.meteofrance.vigilance.department.option.55 = Meuse
+thing-type.config.meteofrance.vigilance.department.option.56 = Morbihan
+thing-type.config.meteofrance.vigilance.department.option.57 = Moselle
+thing-type.config.meteofrance.vigilance.department.option.58 = Nièvre
+thing-type.config.meteofrance.vigilance.department.option.59 = Nord
+thing-type.config.meteofrance.vigilance.department.option.60 = Oise
+thing-type.config.meteofrance.vigilance.department.option.61 = Orne
+thing-type.config.meteofrance.vigilance.department.option.75 = Paris
+thing-type.config.meteofrance.vigilance.department.option.62 = Pas de Calais
+thing-type.config.meteofrance.vigilance.department.option.63 = Puy de Dôme
+thing-type.config.meteofrance.vigilance.department.option.64 = Pyrénées Atlantiques
+thing-type.config.meteofrance.vigilance.department.option.66 = Pyrénées Orientales
+thing-type.config.meteofrance.vigilance.department.option.69 = Rhône
+thing-type.config.meteofrance.vigilance.department.option.71 = Saône et Loire
+thing-type.config.meteofrance.vigilance.department.option.72 = Sarthe
+thing-type.config.meteofrance.vigilance.department.option.73 = Savoie
+thing-type.config.meteofrance.vigilance.department.option.77 = Seine et Marne
+thing-type.config.meteofrance.vigilance.department.option.76 = Seine Maritime
+thing-type.config.meteofrance.vigilance.department.option.93 = Seine Saint Denis
+thing-type.config.meteofrance.vigilance.department.option.80 = Somme
+thing-type.config.meteofrance.vigilance.department.option.81 = Tarn
+thing-type.config.meteofrance.vigilance.department.option.82 = Tarn et Garonne
+thing-type.config.meteofrance.vigilance.department.option.90 = Territoire de Belfort
+thing-type.config.meteofrance.vigilance.department.option.95 = Val D'Oise
+thing-type.config.meteofrance.vigilance.department.option.94 = Val de Marne
+thing-type.config.meteofrance.vigilance.department.option.83 = Var
+thing-type.config.meteofrance.vigilance.department.option.84 = Vaucluse
+thing-type.config.meteofrance.vigilance.department.option.85 = Vendée
+thing-type.config.meteofrance.vigilance.department.option.86 = Vienne
+thing-type.config.meteofrance.vigilance.department.option.88 = Vosges
+thing-type.config.meteofrance.vigilance.department.option.89 = Yonne
+thing-type.config.meteofrance.vigilance.department.option.78 = Yvelines
+thing-type.config.meteofrance.vigilance.refresh.label = Refresh Rate
+thing-type.config.meteofrance.vigilance.refresh.description = Data refresh period in minutes.
+
+# channel types
+
+channel-type.meteofrance.avalanches.label = Avalanches
+channel-type.meteofrance.avalanches.description = Avalanche alert level
+channel-type.meteofrance.avalanches.state.option.0 = No special vigilance
+channel-type.meteofrance.avalanches.state.option.1 = Be attentive
+channel-type.meteofrance.avalanches.state.option.2 = Be very vigilant
+channel-type.meteofrance.avalanches.state.option.3 = Absolute vigilance
+channel-type.meteofrance.canicule.label = Heat Wave
+channel-type.meteofrance.canicule.description = High temperature alert level
+channel-type.meteofrance.canicule.state.option.0 = No special vigilance
+channel-type.meteofrance.canicule.state.option.1 = Be attentive
+channel-type.meteofrance.canicule.state.option.2 = Be very vigilant
+channel-type.meteofrance.canicule.state.option.3 = Absolute vigilance
+channel-type.meteofrance.comment.label = Comment
+channel-type.meteofrance.condition-icon.label = Icon
+channel-type.meteofrance.condition-icon.description = Pictogram associated with the alert level.
+channel-type.meteofrance.grand-froid.label = Extreme Cold
+channel-type.meteofrance.grand-froid.description = Negative temperature alert level
+channel-type.meteofrance.grand-froid.state.option.0 = No special vigilance
+channel-type.meteofrance.grand-froid.state.option.1 = Be attentive
+channel-type.meteofrance.grand-froid.state.option.2 = Be very vigilant
+channel-type.meteofrance.grand-froid.state.option.3 = Absolute vigilance
+channel-type.meteofrance.inondation.label = Flood
+channel-type.meteofrance.inondation.description = Flood alert level
+channel-type.meteofrance.inondation.state.option.0 = No special vigilance
+channel-type.meteofrance.inondation.state.option.1 = Be attentive
+channel-type.meteofrance.inondation.state.option.2 = Be very vigilant
+channel-type.meteofrance.inondation.state.option.3 = Absolute vigilance
+channel-type.meteofrance.neige.label = Snow
+channel-type.meteofrance.neige.description = Snow event alert level
+channel-type.meteofrance.neige.state.option.0 = No special vigilance
+channel-type.meteofrance.neige.state.option.1 = Be attentive
+channel-type.meteofrance.neige.state.option.2 = Be very vigilant
+channel-type.meteofrance.neige.state.option.3 = Absolute vigilance
+channel-type.meteofrance.orage.label = Storm
+channel-type.meteofrance.orage.description = Storm alert level
+channel-type.meteofrance.orage.state.option.0 = No special vigilance
+channel-type.meteofrance.orage.state.option.1 = Be attentive
+channel-type.meteofrance.orage.state.option.2 = Be very vigilant
+channel-type.meteofrance.orage.state.option.3 = Absolute vigilance
+channel-type.meteofrance.pluie-inondation.label = Rain Flood
+channel-type.meteofrance.pluie-inondation.description = Flood caused by rainfall alert level
+channel-type.meteofrance.pluie-inondation.state.option.0 = No special vigilance
+channel-type.meteofrance.pluie-inondation.state.option.1 = Be attentive
+channel-type.meteofrance.pluie-inondation.state.option.2 = Be very vigilant
+channel-type.meteofrance.pluie-inondation.state.option.3 = Absolute vigilance
+channel-type.meteofrance.rain-intensity.label = Intensity
+channel-type.meteofrance.rain-intensity.description = Rain intensity level
+channel-type.meteofrance.rain-intensity.state.option.0 = Dry Weather
+channel-type.meteofrance.rain-intensity.state.option.1 = Light Rain
+channel-type.meteofrance.rain-intensity.state.option.2 = Moderate Rain
+channel-type.meteofrance.rain-intensity.state.option.3 = Heavy Rain
+channel-type.meteofrance.timestamp.label = Observation Timestamp
+channel-type.meteofrance.vague-submersion.label = Wave Submersion
+channel-type.meteofrance.vague-submersion.description = Submersion wave alert level
+channel-type.meteofrance.vague-submersion.state.option.0 = No special vigilance
+channel-type.meteofrance.vague-submersion.state.option.1 = Be attentive
+channel-type.meteofrance.vague-submersion.state.option.2 = Be very vigilant
+channel-type.meteofrance.vague-submersion.state.option.3 = Absolute vigilance
+channel-type.meteofrance.vent.label = Wind
+channel-type.meteofrance.vent.description = Wind event alert level
+channel-type.meteofrance.vent.state.option.0 = No special vigilance
+channel-type.meteofrance.vent.state.option.1 = Be attentive
+channel-type.meteofrance.vent.state.option.2 = Be very vigilant
+channel-type.meteofrance.vent.state.option.3 = Absolute vigilance
+
+# iconprovider
+
+iconset.label = Météo France Icons
+iconset.description = Icons illustrating weather alerts provided by Météo France
+
+# discovery result
+
+discovery.meteofrance.rain-forecast.local.label = Prévisions de Précipitations
+
+# thing status descriptions
+
+offline.config-error-unknown-apikey = Parameter 'apikey' must be configured.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="meteofrance"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+ <bridge-type id="api">
+ <label>Météo-France API Portal</label>
+ <description>
+ Bridge to the Météo-France API Portal. In order to receive the data, you must register an account on
+ https://portail-api.meteofrance.fr/devportal/apis and get your API token.
+ </description>
+ <config-description>
+ <parameter name="apikey" type="text" required="true">
+ <label>API Key</label>
+ <description>Data-platform token to access the service</description>
+ <context>password</context>
+ </parameter>
+ </config-description>
+ </bridge-type>
+
+</thing:thing-descriptions>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="meteofrance"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+ <channel-type id="rain-intensity">
+ <item-type>Number</item-type>
+ <label>Intensity</label>
+ <description>Rain intensity level</description>
+ <category>oh:meteofrance:intensity</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">Dry Weather</option>
+ <option value="1">Light Rain</option>
+ <option value="2">Moderate Rain</option>
+ <option value="3">Heavy Rain</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="vent">
+ <item-type>Number</item-type>
+ <label>Wind</label>
+ <description>Wind event alert level</description>
+ <category>oh:meteofrance:vent</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">No special vigilance</option>
+ <option value="1">Be attentive</option>
+ <option value="2">Be very vigilant</option>
+ <option value="3">Absolute vigilance</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="orage">
+ <item-type>Number</item-type>
+ <label>Storm</label>
+ <description>Storm alert level</description>
+ <category>oh:meteofrance:orage</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">No special vigilance</option>
+ <option value="1">Be attentive</option>
+ <option value="2">Be very vigilant</option>
+ <option value="3">Absolute vigilance</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="inondation">
+ <item-type>Number</item-type>
+ <label>Flood</label>
+ <description>Flood alert level</description>
+ <category>oh:meteofrance:inondation</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">No special vigilance</option>
+ <option value="1">Be attentive</option>
+ <option value="2">Be very vigilant</option>
+ <option value="3">Absolute vigilance</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="neige">
+ <item-type>Number</item-type>
+ <label>Snow</label>
+ <description>Snow event alert level</description>
+ <category>oh:meteofrance:neige</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">No special vigilance</option>
+ <option value="1">Be attentive</option>
+ <option value="2">Be very vigilant</option>
+ <option value="3">Absolute vigilance</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="canicule">
+ <item-type>Number</item-type>
+ <label>Heat Wave</label>
+ <description>High temperature alert level</description>
+ <category>oh:meteofrance:canicule</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">No special vigilance</option>
+ <option value="1">Be attentive</option>
+ <option value="2">Be very vigilant</option>
+ <option value="3">Absolute vigilance</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="grand-froid">
+ <item-type>Number</item-type>
+ <label>Extreme Cold</label>
+ <description>Negative temperature alert level</description>
+ <category>oh:meteofrance:grand-froid</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">No special vigilance</option>
+ <option value="1">Be attentive</option>
+ <option value="2">Be very vigilant</option>
+ <option value="3">Absolute vigilance</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="avalanches">
+ <item-type>Number</item-type>
+ <label>Avalanches</label>
+ <description>Avalanche alert level</description>
+ <category>oh:meteofrance:avalanches</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">No special vigilance</option>
+ <option value="1">Be attentive</option>
+ <option value="2">Be very vigilant</option>
+ <option value="3">Absolute vigilance</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="vague-submersion">
+ <item-type>Number</item-type>
+ <label>Wave Submersion</label>
+ <description>Submersion wave alert level</description>
+ <category>oh:meteofrance:vague-submersion</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">No special vigilance</option>
+ <option value="1">Be attentive</option>
+ <option value="2">Be very vigilant</option>
+ <option value="3">Absolute vigilance</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="pluie-inondation">
+ <item-type>Number</item-type>
+ <label>Rain Flood</label>
+ <description>Flood caused by rainfall alert level</description>
+ <category>oh:meteofrance:pluie-inondation</category>
+ <state readOnly="true">
+ <options>
+ <option value="0">No special vigilance</option>
+ <option value="1">Be attentive</option>
+ <option value="2">Be very vigilant</option>
+ <option value="3">Absolute vigilance</option>
+ </options>
+ </state>
+ </channel-type>
+
+ <channel-type id="comment">
+ <item-type>String</item-type>
+ <label>Comment</label>
+ <category>text</category>
+ <state readOnly="true" pattern="%s"/>
+ </channel-type>
+
+ <channel-type id="timestamp" advanced="true">
+ <item-type>DateTime</item-type>
+ <label>Observation Timestamp</label>
+ <category>time</category>
+ <state readOnly="true"/>
+ </channel-type>
+
+ <channel-type id="condition-icon">
+ <item-type>Image</item-type>
+ <label>Icon</label>
+ <description>Pictogram associated with the alert level.</description>
+ <state readOnly="true"/>
+ </channel-type>
+
+</thing:thing-descriptions>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="meteofrance"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+ <thing-type id="rain-forecast">
+ <supported-bridge-type-refs>
+ <bridge-type-ref id="api"/>
+ </supported-bridge-type-refs>
+ <label>Precipitation Forecast</label>
+ <description>Provides precipitation forecast for the next hour</description>
+
+ <channels>
+ <channel id="update-time" typeId="timestamp"/>
+ <channel id="intensity" typeId="rain-intensity"/>
+ </channels>
+
+ <representation-property>location</representation-property>
+
+ <config-description>
+ <parameter name="location" type="text" required="true">
+ <label>Location</label>
+ <context>location</context>
+ <description>Your geo coordinates separated with comma (e.g. "37.8,-122.4,177").</description>
+ </parameter>
+ </config-description>
+ </thing-type>
+
+</thing:thing-descriptions>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="meteofrance"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+ <thing-type id="vigilance">
+ <supported-bridge-type-refs>
+ <bridge-type-ref id="api"/>
+ </supported-bridge-type-refs>
+
+ <label>Department Awareness</label>
+ <description>Provides weather alert levels for a department.</description>
+
+ <channels>
+ <channel id="vague-submersion" typeId="vague-submersion"/>
+ <channel id="vent" typeId="vent"/>
+ <channel id="pluie-inondation" typeId="pluie-inondation"/>
+ <channel id="orage" typeId="orage"/>
+ <channel id="inondation" typeId="inondation"/>
+ <channel id="neige" typeId="neige"/>
+ <channel id="canicule" typeId="canicule"/>
+ <channel id="grand-froid" typeId="grand-froid"/>
+ <channel id="avalanches" typeId="avalanches"/>
+ <channel id="vague-submersion-icon" typeId="condition-icon">
+ <label>Wave Submersion Icon</label>
+ </channel>
+ <channel id="vent-icon" typeId="condition-icon">
+ <label>Wind Icon</label>
+ </channel>
+ <channel id="pluie-inondation-icon" typeId="condition-icon">
+ <label>Rain Flood Icon</label>
+ </channel>
+ <channel id="orage-icon" typeId="condition-icon">
+ <label>Storm Icon</label>
+ </channel>
+ <channel id="inondation-icon" typeId="condition-icon">
+ <label>Flood Icon</label>
+ </channel>
+ <channel id="neige-icon" typeId="condition-icon">
+ <label>Snow Icon</label>
+ </channel>
+ <channel id="canicule-icon" typeId="condition-icon">
+ <label>Heat Wave Icon</label>
+ </channel>
+ <channel id="grand-froid-icon" typeId="condition-icon">
+ <label>Extreme Cold Icon</label>
+ </channel>
+ <channel id="avalanches-icon" typeId="condition-icon">
+ <label>Avalanche Icon</label>
+ </channel>
+ <channel id="comment" typeId="comment"/>
+ <channel id="observation-time" typeId="timestamp">
+ <label>Start of Validity</label>
+ </channel>
+ <channel id="end-time" typeId="timestamp">
+ <label>End of Validity</label>
+ </channel>
+ </channels>
+
+ <representation-property>department</representation-property>
+
+ <config-description>
+ <parameter name="department" type="text" required="true">
+ <label>Department</label>
+ <description>Name of the department</description>
+ <options>
+ <option value="01">Ain</option>
+ <option value="02">Aisne</option>
+ <option value="03">Allier</option>
+ <option value="04">Alpes de Haute Provence</option>
+ <option value="06">Alpes Maritimes</option>
+ <option value="07">Ardèche</option>
+ <option value="08">Ardennes</option>
+ <option value="09">Ariège</option>
+ <option value="10">Aube</option>
+ <option value="11">Aude</option>
+ <option value="12">Aveyron</option>
+ <option value="67">Bas-Rhin</option>
+ <option value="13">Bouches du Rhône</option>
+ <option value="14">Calvados</option>
+ <option value="15">Cantal</option>
+ <option value="16">Charente</option>
+ <option value="17">Charente Maritime</option>
+ <option value="18">Cher</option>
+ <option value="19">Corrèze</option>
+ <option value="2A">Corse du Sud</option>
+ <option value="21">Côte D'Or</option>
+ <option value="22">Côtes D'Armor</option>
+ <option value="23">Creuse</option>
+ <option value="79">Deux Sèvres</option>
+ <option value="24">Dordogne</option>
+ <option value="25">Doubs</option>
+ <option value="26">Drôme</option>
+ <option value="91">Essonne</option>
+ <option value="27">Eure</option>
+ <option value="28">Eure et Loir</option>
+ <option value="29">Finistère</option>
+ <option value="30">Gard</option>
+ <option value="32">Gers</option>
+ <option value="33">Gironde</option>
+ <option value="68">Haut-Rhin</option>
+ <option value="2B">Haute Corse</option>
+ <option value="31">Haute Garonne</option>
+ <option value="43">Haute Loire</option>
+ <option value="52">Haute Marne</option>
+ <option value="70">Haute Saône</option>
+ <option value="74">Haute Savoie</option>
+ <option value="87">Haute Vienne</option>
+ <option value="05">Hautes Alpes</option>
+ <option value="65">Hautes Pyrénées</option>
+ <option value="92">Hauts de Seine</option>
+ <option value="34">Hérault</option>
+ <option value="35">Ille et Vilaine</option>
+ <option value="36">Indre</option>
+ <option value="37">Indre et Loire</option>
+ <option value="38">Isère</option>
+ <option value="39">Jura</option>
+ <option value="40">Landes</option>
+ <option value="41">Loir et Cher</option>
+ <option value="42">Loire</option>
+ <option value="44">Loire Atlantique</option>
+ <option value="45">Loiret</option>
+ <option value="46">Lot</option>
+ <option value="47">Lot et Garonne</option>
+ <option value="48">Lozère</option>
+ <option value="49">Maine et Loire</option>
+ <option value="50">Manche</option>
+ <option value="51">Marne</option>
+ <option value="53">Mayenne</option>
+ <option value="54">Meurthe et Moselle</option>
+ <option value="55">Meuse</option>
+ <option value="56">Morbihan</option>
+ <option value="57">Moselle</option>
+ <option value="58">Nièvre</option>
+ <option value="59">Nord</option>
+ <option value="60">Oise</option>
+ <option value="61">Orne</option>
+ <option value="75">Paris</option>
+ <option value="62">Pas de Calais</option>
+ <option value="63">Puy de Dôme</option>
+ <option value="64">Pyrénées Atlantiques</option>
+ <option value="66">Pyrénées Orientales</option>
+ <option value="69">Rhône</option>
+ <option value="71">Saône et Loire</option>
+ <option value="72">Sarthe</option>
+ <option value="73">Savoie</option>
+ <option value="77">Seine et Marne</option>
+ <option value="76">Seine Maritime</option>
+ <option value="93">Seine Saint Denis</option>
+ <option value="80">Somme</option>
+ <option value="81">Tarn</option>
+ <option value="82">Tarn et Garonne</option>
+ <option value="90">Territoire de Belfort</option>
+ <option value="95">Val D'Oise</option>
+ <option value="94">Val de Marne</option>
+ <option value="83">Var</option>
+ <option value="84">Vaucluse</option>
+ <option value="85">Vendée</option>
+ <option value="86">Vienne</option>
+ <option value="88">Vosges</option>
+ <option value="89">Yonne</option>
+ <option value="78">Yvelines</option>
+ </options>
+ <limitToOptions>true</limitToOptions>
+ </parameter>
+ <parameter name="refresh" type="integer" min="1" required="true" unit="min">
+ <label>Refresh Rate</label>
+ <description>Data refresh period in minutes.</description>
+ <default>60</default>
+ </parameter>
+ </config-description>
+ </thing-type>
+
+</thing:thing-descriptions>
--- /dev/null
+[\r
+ {\r
+ "id": "01",\r
+ "name": "Ain",\r
+ "northest_lat": 46.517199374492,\r
+ "southest_lat": 45.611235124481,\r
+ "eastest_lon": 6.1697363568789,\r
+ "westest_lon": 4.729097034294\r
+ },\r
+ {\r
+ "id": "02",\r
+ "name": "Aisne",\r
+ "northest_lat": 50.069271974234,\r
+ "southest_lat": 48.837795469902,\r
+ "eastest_lon": 4.2540638814402,\r
+ "westest_lon": 2.9624508927558\r
+ },\r
+ {\r
+ "id": "03",\r
+ "name": "Allier",\r
+ "northest_lat": 46.803872076205,\r
+ "southest_lat": 45.930727869968,\r
+ "eastest_lon": 4.0055701432229,\r
+ "westest_lon": 2.2804029533754\r
+ },\r
+ {\r
+ "id": "04",\r
+ "name": "Alpes-de-Haute-Provence",\r
+ "northest_lat": 44.659501345682,\r
+ "southest_lat": 43.668282105491,\r
+ "eastest_lon": 6.9668199032047,\r
+ "westest_lon": 5.4980104773442\r
+ },\r
+ {\r
+ "id": "05",\r
+ "name": "Hautes-Alpes",\r
+ "northest_lat": 45.12684420383,\r
+ "southest_lat": 44.186478874057,\r
+ "eastest_lon": 7.0771048243018,\r
+ "westest_lon": 5.4185330627929\r
+ },\r
+ {\r
+ "id": "06",\r
+ "name": "Alpes-Maritimes",\r
+ "northest_lat": 44.361051257141,\r
+ "southest_lat": 43.480065494401,\r
+ "eastest_lon": 7.7169378581589,\r
+ "westest_lon": 6.6363906079569\r
+ },\r
+ {\r
+ "id": "07",\r
+ "name": "Ardèche",\r
+ "northest_lat": 45.365674921417,\r
+ "southest_lat": 44.264783733394,\r
+ "eastest_lon": 4.8865943991285,\r
+ "westest_lon": 3.8615128126047\r
+ },\r
+ {\r
+ "id": "08",\r
+ "name": "Ardennes",\r
+ "northest_lat": 50.168317417174,\r
+ "southest_lat": 49.228510768771,\r
+ "eastest_lon": 5.3935393812988,\r
+ "westest_lon": 4.0252899216328\r
+ },\r
+ {\r
+ "id": "09",\r
+ "name": "Ariège",\r
+ "northest_lat": 43.315601482419,\r
+ "southest_lat": 42.572397819345,\r
+ "eastest_lon": 2.1758766074869,\r
+ "westest_lon": 0.82612266137771\r
+ },\r
+ {\r
+ "id": "10",\r
+ "name": "Aube",\r
+ "northest_lat": 48.716672523486,\r
+ "southest_lat": 47.924112631788,\r
+ "eastest_lon": 4.863174195777,\r
+ "westest_lon": 3.3883584814447\r
+ },\r
+ {\r
+ "id": "11",\r
+ "name": "Aude",\r
+ "northest_lat": 43.459927734352,\r
+ "southest_lat": 42.64890098195,\r
+ "eastest_lon": 3.2405623482295,\r
+ "westest_lon": 1.6884233932357\r
+ },\r
+ {\r
+ "id": "12",\r
+ "name": "Aveyron",\r
+ "northest_lat": 44.941219492647,\r
+ "southest_lat": 43.692056102371,\r
+ "eastest_lon": 3.4507554815828,\r
+ "westest_lon": 1.8396044963184\r
+ },\r
+ {\r
+ "id": "13",\r
+ "name": "Bouches-du-Rhône",\r
+ "northest_lat": 43.92406219253,\r
+ "southest_lat": 43.162545513212,\r
+ "eastest_lon": 5.8132476569219,\r
+ "westest_lon": 4.2302808850321\r
+ },\r
+ {\r
+ "id": "14",\r
+ "name": "Calvados",\r
+ "northest_lat": 49.429859840723,\r
+ "southest_lat": 48.752223582274,\r
+ "eastest_lon": 0.44627431224134,\r
+ "westest_lon": -1.1595014604014\r
+ },\r
+ {\r
+ "id": "15",\r
+ "name": "Cantal",\r
+ "northest_lat": 45.480702895801,\r
+ "southest_lat": 44.61552895784,\r
+ "eastest_lon": 3.3699091459722,\r
+ "westest_lon": 2.0629079799591\r
+ },\r
+ {\r
+ "id": "16",\r
+ "name": "Charente",\r
+ "northest_lat": 46.139591492141,\r
+ "southest_lat": 45.191628193392,\r
+ "eastest_lon": 0.9456207917489,\r
+ "westest_lon": -0.46177341555077\r
+ },\r
+ {\r
+ "id": "17",\r
+ "name": "Charente-Maritime",\r
+ "northest_lat": 46.371051399922,\r
+ "southest_lat": 45.088810634907,\r
+ "eastest_lon": 0.005823224821197,\r
+ "westest_lon": -1.5614800452621\r
+ },\r
+ {\r
+ "id": "18",\r
+ "name": "Cher",\r
+ "northest_lat": 47.628965936616,\r
+ "southest_lat": 46.420403547753,\r
+ "eastest_lon": 3.0793324170792,\r
+ "westest_lon": 1.7745852665449\r
+ },\r
+ {\r
+ "id": "19",\r
+ "name": "Corrèze",\r
+ "northest_lat": 45.763895555756,\r
+ "southest_lat": 44.923721627249,\r
+ "eastest_lon": 2.5283596411119,\r
+ "westest_lon": 1.2271245972559\r
+ },\r
+ {\r
+ "id": "21",\r
+ "name": "Côte-d'Or",\r
+ "northest_lat": 48.030241950581,\r
+ "southest_lat": 46.900857518168,\r
+ "eastest_lon": 5.5185372800929,\r
+ "westest_lon": 4.0660574486622\r
+ },\r
+ {\r
+ "id": "22",\r
+ "name": "Côtes-d'Armor",\r
+ "northest_lat": 48.867411825697,\r
+ "southest_lat": 48.035478415172,\r
+ "eastest_lon": -1.9089921410274,\r
+ "westest_lon": -3.663669588163\r
+ },\r
+ {\r
+ "id": "23",\r
+ "name": "Creuse",\r
+ "northest_lat": 46.45481310551,\r
+ "southest_lat": 45.664008285608,\r
+ "eastest_lon": 2.6107853057918,\r
+ "westest_lon": 1.3748978470741\r
+ },\r
+ {\r
+ "id": "24",\r
+ "name": "Dordogne",\r
+ "northest_lat": 45.714569962764,\r
+ "southest_lat": 44.57129825478,\r
+ "eastest_lon": 1.4482602497483,\r
+ "westest_lon": -0.041998525054412\r
+ },\r
+ {\r
+ "id": "25",\r
+ "name": "Doubs",\r
+ "northest_lat": 47.579897594928,\r
+ "southest_lat": 46.553996454277,\r
+ "eastest_lon": 7.0622006908671,\r
+ "westest_lon": 5.6987272452696\r
+ },\r
+ {\r
+ "id": "26",\r
+ "name": "Drôme",\r
+ "northest_lat": 45.344042230781,\r
+ "southest_lat": 44.115716677493,\r
+ "eastest_lon": 5.8294720463131,\r
+ "westest_lon": 4.6477668446587\r
+ },\r
+ {\r
+ "id": "27",\r
+ "name": "Eure",\r
+ "northest_lat": 49.485111873749,\r
+ "southest_lat": 48.666521479531,\r
+ "eastest_lon": 1.8026740663848,\r
+ "westest_lon": 0.29722451460974\r
+ },\r
+ {\r
+ "id": "28",\r
+ "name": "Eure-et-Loir",\r
+ "northest_lat": 48.941051842112,\r
+ "southest_lat": 47.953852019595,\r
+ "eastest_lon": 1.9940901445311,\r
+ "westest_lon": 0.76023175104941\r
+ },\r
+ {\r
+ "id": "29",\r
+ "name": "Finistère",\r
+ "northest_lat": 48.75230874743,\r
+ "southest_lat": 47.762638930067,\r
+ "eastest_lon": -3.3880788564101,\r
+ "westest_lon": -5.138001239929\r
+ },\r
+ {\r
+ "id": "30",\r
+ "name": "Gard",\r
+ "northest_lat": 44.459798467391,\r
+ "southest_lat": 43.460183661653,\r
+ "eastest_lon": 4.8455501032842,\r
+ "westest_lon": 3.2628340569911\r
+ },\r
+ {\r
+ "id": "31",\r
+ "name": "Haute-Garonne",\r
+ "northest_lat": 43.920240096152,\r
+ "southest_lat": 42.68989270234,\r
+ "eastest_lon": 2.0478554672695,\r
+ "westest_lon": 0.44199364903152\r
+ },\r
+ {\r
+ "id": "32",\r
+ "name": "Gers",\r
+ "northest_lat": 44.078224550392,\r
+ "southest_lat": 43.310884111508,\r
+ "eastest_lon": 1.2013345895525,\r
+ "westest_lon": -0.28211623210758\r
+ },\r
+ {\r
+ "id": "33",\r
+ "name": "Gironde",\r
+ "northest_lat": 45.574691325999,\r
+ "southest_lat": 44.193811119459,\r
+ "eastest_lon": 0.31506020240148,\r
+ "westest_lon": -1.2617334302552\r
+ },\r
+ {\r
+ "id": "34",\r
+ "name": "Hérault",\r
+ "northest_lat": 43.969527164685,\r
+ "southest_lat": 43.212804132866,\r
+ "eastest_lon": 4.1944474773799,\r
+ "westest_lon": 2.5399656073586\r
+ },\r
+ {\r
+ "id": "35",\r
+ "name": "Ille-et-Vilaine",\r
+ "northest_lat": 48.704854504824,\r
+ "southest_lat": 47.631356309182,\r
+ "eastest_lon": -1.0168893967587,\r
+ "westest_lon": -2.289084836122\r
+ },\r
+ {\r
+ "id": "36",\r
+ "name": "Indre",\r
+ "northest_lat": 47.276819032313,\r
+ "southest_lat": 46.347214822447,\r
+ "eastest_lon": 2.2043920861378,\r
+ "westest_lon": 0.86746898682573\r
+ },\r
+ {\r
+ "id": "37",\r
+ "name": "Indre-et-Loire",\r
+ "northest_lat": 47.709346222795,\r
+ "southest_lat": 46.737086924375,\r
+ "eastest_lon": 1.3653663291974,\r
+ "westest_lon": 0.053277684947378\r
+ },\r
+ {\r
+ "id": "38",\r
+ "name": "Isère",\r
+ "northest_lat": 45.883269928025,\r
+ "southest_lat": 44.696067584965,\r
+ "eastest_lon": 6.3588423781754,\r
+ "westest_lon": 4.7441167394752\r
+ },\r
+ {\r
+ "id": "39",\r
+ "name": "Jura",\r
+ "northest_lat": 47.305475313171,\r
+ "southest_lat": 46.260731935709,\r
+ "eastest_lon": 6.2033299339615,\r
+ "westest_lon": 5.2548827302617\r
+ },\r
+ {\r
+ "id": "40",\r
+ "name": "Landes",\r
+ "northest_lat": 44.532195517275,\r
+ "southest_lat": 43.487949116697,\r
+ "eastest_lon": 0.13672631290526,\r
+ "westest_lon": -1.524870110434\r
+ },\r
+ {\r
+ "id": "41",\r
+ "name": "Loir-et-Cher",\r
+ "northest_lat": 48.132548568904,\r
+ "southest_lat": 47.18622172903,\r
+ "eastest_lon": 2.2478931361182,\r
+ "westest_lon": 0.58052041667909\r
+ },\r
+ {\r
+ "id": "42",\r
+ "name": "Loire",\r
+ "northest_lat": 46.275936357353,\r
+ "southest_lat": 45.232177394436,\r
+ "eastest_lon": 4.7604638818845,\r
+ "westest_lon": 3.6906909501902\r
+ },\r
+ {\r
+ "id": "43",\r
+ "name": "Haute-Loire",\r
+ "northest_lat": 45.427582294546,\r
+ "southest_lat": 44.743866105932,\r
+ "eastest_lon": 4.489606977621,\r
+ "westest_lon": 3.0822533822787\r
+ },\r
+ {\r
+ "id": "44",\r
+ "name": "Loire-Atlantique",\r
+ "northest_lat": 47.833557723029,\r
+ "southest_lat": 46.860078088448,\r
+ "eastest_lon": -0.94643916329696,\r
+ "westest_lon": -2.5589448655806\r
+ },\r
+ {\r
+ "id": "45",\r
+ "name": "Loiret",\r
+ "northest_lat": 48.344598562828,\r
+ "southest_lat": 47.482968445146,\r
+ "eastest_lon": 3.1284487900515,\r
+ "westest_lon": 1.5129691249084\r
+ },\r
+ {\r
+ "id": "46",\r
+ "name": "Lot",\r
+ "northest_lat": 45.046275852749,\r
+ "southest_lat": 44.204018679795,\r
+ "eastest_lon": 2.2108934010391,\r
+ "westest_lon": 0.98177646477517\r
+ },\r
+ {\r
+ "id": "47",\r
+ "name": "Lot-et-Garonne",\r
+ "northest_lat": 44.764390535693,\r
+ "southest_lat": 43.973860568873,\r
+ "eastest_lon": 1.0779367166615,\r
+ "westest_lon": -0.14068987994571\r
+ },\r
+ {\r
+ "id": "48",\r
+ "name": "Lozère",\r
+ "northest_lat": 44.971408091786,\r
+ "southest_lat": 44.113818175271,\r
+ "eastest_lon": 3.9981617468281,\r
+ "westest_lon": 2.981675726654\r
+ },\r
+ {\r
+ "id": "49",\r
+ "name": "Maine-et-Loire",\r
+ "northest_lat": 47.809992506553,\r
+ "southest_lat": 46.969397597368,\r
+ "eastest_lon": 0.23453049018557,\r
+ "westest_lon": -1.3541992398083\r
+ },\r
+ {\r
+ "id": "50",\r
+ "name": "Manche",\r
+ "northest_lat": 49.725557927402,\r
+ "southest_lat": 48.458282754255,\r
+ "eastest_lon": -0.73732101904671,\r
+ "westest_lon": -1.9472733176655\r
+ },\r
+ {\r
+ "id": "51",\r
+ "name": "Marne",\r
+ "northest_lat": 49.406179032892,\r
+ "southest_lat": 48.516108006569,\r
+ "eastest_lon": 5.0379027924329,\r
+ "westest_lon": 3.398657955437\r
+ },\r
+ {\r
+ "id": "52",\r
+ "name": "Haute-Marne",\r
+ "northest_lat": 48.688711618117,\r
+ "southest_lat": 47.576950536437,\r
+ "eastest_lon": 5.8908642780035,\r
+ "westest_lon": 4.6268310932286\r
+ },\r
+ {\r
+ "id": "53",\r
+ "name": "Mayenne",\r
+ "northest_lat": 48.567994064435,\r
+ "southest_lat": 47.733379704738,\r
+ "eastest_lon": -0.049909790963035,\r
+ "westest_lon": -1.238247803597\r
+ },\r
+ {\r
+ "id": "54",\r
+ "name": "Meurthe-et-Moselle",\r
+ "northest_lat": 49.562644003065,\r
+ "southest_lat": 48.349889737943,\r
+ "eastest_lon": 7.1231636635608,\r
+ "westest_lon": 5.429907860027\r
+ },\r
+ {\r
+ "id": "55",\r
+ "name": "Meuse",\r
+ "northest_lat": 49.617086785829,\r
+ "southest_lat": 48.410687855212,\r
+ "eastest_lon": 5.8541770017029,\r
+ "westest_lon": 4.8885820531146\r
+ },\r
+ {\r
+ "id": "56",\r
+ "name": "Morbihan",\r
+ "northest_lat": 48.210884763611,\r
+ "southest_lat": 47.283069445657,\r
+ "eastest_lon": -2.0357552590146,\r
+ "westest_lon": -3.7321436369252\r
+ },\r
+ {\r
+ "id": "57",\r
+ "name": "Moselle",\r
+ "northest_lat": 49.510019040716,\r
+ "southest_lat": 48.52694525177,\r
+ "eastest_lon": 7.6352815933424,\r
+ "westest_lon": 5.8934039932125\r
+ },\r
+ {\r
+ "id": "58",\r
+ "name": "Nièvre",\r
+ "northest_lat": 47.587958865747,\r
+ "southest_lat": 46.651760006926,\r
+ "eastest_lon": 4.2306617272065,\r
+ "westest_lon": 2.8451871650071\r
+ },\r
+ {\r
+ "id": "59",\r
+ "name": "Nord",\r
+ "northest_lat": 51.08854370897,\r
+ "southest_lat": 49.969186662527,\r
+ "eastest_lon": 4.2279959931456,\r
+ "westest_lon": 2.0677049871716\r
+ },\r
+ {\r
+ "id": "60",\r
+ "name": "Oise",\r
+ "northest_lat": 49.758309270134,\r
+ "southest_lat": 49.060452516659,\r
+ "eastest_lon": 3.162641421643,\r
+ "westest_lon": 1.6895744511517\r
+ },\r
+ {\r
+ "id": "61",\r
+ "name": "Orne",\r
+ "northest_lat": 48.972557592954,\r
+ "southest_lat": 48.181599665308,\r
+ "eastest_lon": 0.9762713097259,\r
+ "westest_lon": -0.86036021134895\r
+ },\r
+ {\r
+ "id": "62",\r
+ "name": "Pas-de-Calais",\r
+ "northest_lat": 51.006501514321,\r
+ "southest_lat": 50.020975633738,\r
+ "eastest_lon": 3.1883563131291,\r
+ "westest_lon": 1.5577948179294\r
+ },\r
+ {\r
+ "id": "63",\r
+ "name": "Puy-de-Dôme",\r
+ "northest_lat": 46.255486133208,\r
+ "southest_lat": 45.287121578381,\r
+ "eastest_lon": 3.9844000097893,\r
+ "westest_lon": 2.388014020679\r
+ },\r
+ {\r
+ "id": "64",\r
+ "name": "Pyrénées-Atlantiques",\r
+ "northest_lat": 43.596401195938,\r
+ "southest_lat": 42.777515930774,\r
+ "eastest_lon": 0.02629551293813,\r
+ "westest_lon": -1.7908870919282\r
+ },\r
+ {\r
+ "id": "65",\r
+ "name": "Hautes-Pyrénées",\r
+ "northest_lat": 43.609311711216,\r
+ "southest_lat": 42.674921018438,\r
+ "eastest_lon": 0.64553925526757,\r
+ "westest_lon": -0.3270823405503\r
+ },\r
+ {\r
+ "id": "66",\r
+ "name": "Pyrénées-Orientales",\r
+ "northest_lat": 42.918339638726,\r
+ "southest_lat": 42.33364688988,\r
+ "eastest_lon": 3.1747892794105,\r
+ "westest_lon": 1.7256472450279\r
+ },\r
+ {\r
+ "id": "67",\r
+ "name": "Bas-Rhin",\r
+ "northest_lat": 49.077884925649,\r
+ "southest_lat": 48.120371112534,\r
+ "eastest_lon": 8.2303986615424,\r
+ "westest_lon": 6.9403717864006\r
+ },\r
+ {\r
+ "id": "68",\r
+ "name": "Haut-Rhin",\r
+ "northest_lat": 48.310471263573,\r
+ "southest_lat": 47.422198455938,\r
+ "eastest_lon": 7.6220859200517,\r
+ "westest_lon": 6.8428287756472\r
+ },\r
+ {\r
+ "id": "69",\r
+ "name": "Rhône",\r
+ "northest_lat": 46.303994122044,\r
+ "southest_lat": 45.45503324486,\r
+ "eastest_lon": 5.1592030475156,\r
+ "westest_lon": 4.243469905983\r
+ },\r
+ {\r
+ "id": "70",\r
+ "name": "Haute-Saône",\r
+ "northest_lat": 48.023714993889,\r
+ "southest_lat": 47.253139353829,\r
+ "eastest_lon": 6.8235333222471,\r
+ "westest_lon": 5.3727580571009\r
+ },\r
+ {\r
+ "id": "71",\r
+ "name": "Saône-et-Loire",\r
+ "northest_lat": 47.155410810959,\r
+ "southest_lat": 46.156946471815,\r
+ "eastest_lon": 5.4622983197648,\r
+ "westest_lon": 3.6225898833129\r
+ },\r
+ {\r
+ "id": "72",\r
+ "name": "Sarthe",\r
+ "northest_lat": 48.482954540393,\r
+ "southest_lat": 47.569104805534,\r
+ "eastest_lon": 0.91379809767445,\r
+ "westest_lon": -0.44786007819229\r
+ },\r
+ {\r
+ "id": "73",\r
+ "name": "Savoie",\r
+ "northest_lat": 45.93845768164,\r
+ "southest_lat": 45.051837207667,\r
+ "eastest_lon": 7.1842712160815,\r
+ "westest_lon": 5.6230208703548\r
+ },\r
+ {\r
+ "id": "74",\r
+ "name": "Haute-Savoie",\r
+ "northest_lat": 46.408081546332,\r
+ "southest_lat": 45.682198985672,\r
+ "eastest_lon": 7.0438913499404,\r
+ "westest_lon": 5.8074048290847\r
+ },\r
+ {\r
+ "id": "75",\r
+ "name": "Paris",\r
+ "northest_lat": 48.902007785215,\r
+ "southest_lat": 48.816314210034,\r
+ "eastest_lon": 2.4675819883673,\r
+ "westest_lon": 2.2242191058804\r
+ },\r
+ {\r
+ "id": "76",\r
+ "name": "Seine-Maritime",\r
+ "northest_lat": 50.070851596042,\r
+ "southest_lat": 49.252262168305,\r
+ "eastest_lon": 1.79022549105,\r
+ "westest_lon": 0.065609431053556\r
+ },\r
+ {\r
+ "id": "77",\r
+ "name": "Seine-et-Marne",\r
+ "northest_lat": 49.11755332218,\r
+ "southest_lat": 48.122204261229,\r
+ "eastest_lon": 3.555613758785,\r
+ "westest_lon": 2.3931765378081\r
+ },\r
+ {\r
+ "id": "78",\r
+ "name": "Yvelines",\r
+ "northest_lat": 49.08303659502,\r
+ "southest_lat": 48.440146719021,\r
+ "eastest_lon": 2.2265538842831,\r
+ "westest_lon": 1.4472851104304\r
+ },\r
+ {\r
+ "id": "79",\r
+ "name": "Deux-Sèvres",\r
+ "northest_lat": 47.108333434925,\r
+ "southest_lat": 45.969661749473,\r
+ "eastest_lon": 0.22035828616308,\r
+ "westest_lon": -0.89196408624284\r
+ },\r
+ {\r
+ "id": "80",\r
+ "name": "Somme",\r
+ "northest_lat": 50.366290636763,\r
+ "southest_lat": 49.571762327,\r
+ "eastest_lon": 3.2030417908111,\r
+ "westest_lon": 1.3796981484469\r
+ },\r
+ {\r
+ "id": "81",\r
+ "name": "Tarn",\r
+ "northest_lat": 44.200834436147,\r
+ "southest_lat": 43.383508824887,\r
+ "eastest_lon": 2.93545676901,\r
+ "westest_lon": 1.5439759556659\r
+ },\r
+ {\r
+ "id": "82",\r
+ "name": "Tarn-et-Garonne",\r
+ "northest_lat": 44.393331095059,\r
+ "southest_lat": 43.770780304363,\r
+ "eastest_lon": 1.9963637896774,\r
+ "westest_lon": 0.73810974125492\r
+ },\r
+ {\r
+ "id": "83",\r
+ "name": "Var",\r
+ "northest_lat": 43.806770970879,\r
+ "southest_lat": 42.982043008785,\r
+ "eastest_lon": 6.9337211159516,\r
+ "westest_lon": 5.6559638228901\r
+ },\r
+ {\r
+ "id": "84",\r
+ "name": "Vaucluse",\r
+ "northest_lat": 44.431367227183,\r
+ "southest_lat": 43.658685905188,\r
+ "eastest_lon": 5.7573377215236,\r
+ "westest_lon": 4.649227423465\r
+ },\r
+ {\r
+ "id": "85",\r
+ "name": "Vendée",\r
+ "northest_lat": 47.083893903306,\r
+ "southest_lat": 46.266566974958,\r
+ "eastest_lon": -0.53779518169029,\r
+ "westest_lon": -2.3987614706025\r
+ },\r
+ {\r
+ "id": "86",\r
+ "name": "Vienne",\r
+ "northest_lat": 47.175754285742,\r
+ "southest_lat": 46.049008552161,\r
+ "eastest_lon": 1.2126877519811,\r
+ "westest_lon": -0.1021158452812\r
+ },\r
+ {\r
+ "id": "87",\r
+ "name": "Haute-Vienne",\r
+ "northest_lat": 46.401546863371,\r
+ "southest_lat": 45.437356928582,\r
+ "eastest_lon": 1.9094484810021,\r
+ "westest_lon": 0.62974117909144\r
+ },\r
+ {\r
+ "id": "88",\r
+ "name": "Vosges",\r
+ "northest_lat": 48.513587820739,\r
+ "southest_lat": 47.813051201983,\r
+ "eastest_lon": 7.1982872111206,\r
+ "westest_lon": 5.3944755711529\r
+ },\r
+ {\r
+ "id": "89",\r
+ "name": "Yonne",\r
+ "northest_lat": 48.39970411104,\r
+ "southest_lat": 47.312769315752,\r
+ "eastest_lon": 4.3403007872795,\r
+ "westest_lon": 2.8487899744432\r
+ },\r
+ {\r
+ "id": "90",\r
+ "name": "Territoire de Belfort",\r
+ "northest_lat": 47.824784354742,\r
+ "southest_lat": 47.433371743667,\r
+ "eastest_lon": 7.1398015507652,\r
+ "westest_lon": 6.7576409592057\r
+ },\r
+ {\r
+ "id": "91",\r
+ "name": "Essonne",\r
+ "northest_lat": 48.776101996393,\r
+ "southest_lat": 48.284688606385,\r
+ "eastest_lon": 2.5853737107586,\r
+ "westest_lon": 1.9149199821626\r
+ },\r
+ {\r
+ "id": "92",\r
+ "name": "Hauts-de-Seine",\r
+ "northest_lat": 48.950965864655,\r
+ "southest_lat": 48.72948996497,\r
+ "eastest_lon": 2.3363529889891,\r
+ "westest_lon": 2.1458760215967\r
+ },\r
+ {\r
+ "id": "93",\r
+ "name": "Seine-Saint-Denis",\r
+ "northest_lat": 49.012397786393,\r
+ "southest_lat": 48.807437551952,\r
+ "eastest_lon": 2.6025997962059,\r
+ "westest_lon": 2.2882536989787\r
+ },\r
+ {\r
+ "id": "94",\r
+ "name": "Val-de-Marne",\r
+ "northest_lat": 48.861405371284,\r
+ "southest_lat": 48.688326690701,\r
+ "eastest_lon": 2.6136517425679,\r
+ "westest_lon": 2.3102224901101\r
+ },\r
+ {\r
+ "id": "95",\r
+ "name": "Val-d'Oise",\r
+ "northest_lat": 49.232197221792,\r
+ "southest_lat": 48.908679329899,\r
+ "eastest_lon": 2.5905283926735,\r
+ "westest_lon": 1.608798807603\r
+ },\r
+ {\r
+ "id": "2A",\r
+ "name": "Corse-du-Sud",\r
+ "northest_lat": 42.381404942274,\r
+ "southest_lat": 41.362164776515,\r
+ "eastest_lon": 9.4073217319481,\r
+ "westest_lon": 8.5401025407511\r
+ },\r
+ {\r
+ "id": "2B",\r
+ "name": "Haute-Corse",\r
+ "northest_lat": 43.011724041684,\r
+ "southest_lat": 41.832143660252,\r
+ "eastest_lon": 9.5592262719626,\r
+ "westest_lon": 8.5734085639674\r
+ }\r
+]
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <g transform="matrix(0.095654, 0, 0, 0.103801, 7.65905, -0.7645)" style="">
+ <g>
+ <path style="fill:#9B5C5C;" d="M277.259,58.637c-11.695-20.344-30.835-20.344-42.53,0L4.978,432.587 c-11.695,20.342-2.07,36.966,21.398,36.966h459.235c23.468,0,33.093-16.624,21.405-36.966L277.259,58.637z"/>
+ <path style="fill:#9B5C5C;" d="M277.259,57.683c-11.695-20.328-30.835-20.328-42.53,0l-23.538,59.732l-32.538,31.78L4.978,432.587 c-11.695,20.342-2.07,36.966,21.398,36.966h459.235c23.468,0,33.093-16.624,21.405-36.966l-56.124-91.592l-84.06-104.052 L277.259,57.683z"/>
+ </g>
+ <g>
+ <path style="fill:#CBD0D8;" d="M426.629,226.272c-23.562,0-42.671,19.108-42.671,42.671c0,23.554,19.109,42.646,42.671,42.646 c23.545,0,42.654-19.093,42.654-42.646C469.283,245.381,450.174,226.272,426.629,226.272L426.629,226.272z"/>
+ <path style="fill:#CBD0D8;" d="M394.63,226.272c0,5.89-4.766,10.671-10.672,10.671c-5.875,0-10.656-4.781-10.656-10.671 c0-5.875,4.781-10.656,10.656-10.656C389.864,215.616,394.63,220.397,394.63,226.272z"/>
+ <path style="fill:#CBD0D8;" d="M426.629,204.944c0,5.891-4.781,10.672-10.671,10.672c-5.891,0-10.656-4.781-10.656-10.672 s4.766-10.655,10.656-10.655C421.848,194.289,426.629,199.054,426.629,204.944z"/>
+ <path style="fill:#CBD0D8;" d="M383.958,183.617c0,5.891-4.766,10.672-10.656,10.672s-10.656-4.781-10.656-10.672 s4.766-10.656,10.656-10.656S383.958,177.726,383.958,183.617z"/>
+ <path style="fill:#CBD0D8;" d="M351.974,151.634c0,5.891-4.766,10.655-10.672,10.655c-5.874,0-10.655-4.765-10.655-10.655 s4.781-10.671,10.655-10.671C347.209,140.963,351.974,145.744,351.974,151.634z"/>
+ </g>
+ <path style="fill:#E6E9ED;" d="M 273.368 152.384 C 274.649 151.868 275.993 151.634 277.321 151.634 C 280.992 151.634 284.554 153.54 286.523 156.884 C 286.523 156.884 355.865 257.194 381.786 300.341 C 407.708 343.495 450.892 341.027 450.892 341.027 L 277.259 57.683 C 265.564 37.355 246.424 37.355 234.729 57.683 L 178.653 149.196 C 178.653 149.196 210.879 171.539 225.503 171.539 C 240.126 171.539 273.368 152.384 273.368 152.384 Z"/>
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
+ <g fill="#dae1e4">
+ <circle cx="32" cy="55" r="9" />
+ <circle cx="32" cy="6" r="6" />
+ </g>
+ <circle cx="32" cy="6" r="5" fill="#d20014" />
+ <path d="m26 6h12v50h-12z" fill="#dae1e4" />
+ <g fill="#d20014">
+ <path d="m27 6h10v48.94h-10z" />
+ <circle cx="32" cy="55" r="8" />
+ </g>
+ <g fill="#fff">
+ <path d="m33 9h5v2h-5z" />
+ <path d="m33 17h5v2h-5z" />
+ <path d="m33 25h5v2h-5z" />
+ <path d="m33 33h5v2h-5z" />
+ <path d="m33 41h5v2h-5z" />
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
+ <circle cx="32" cy="6" r="6" fill="#dae1e4" />
+ <circle cx="32" cy="6" r="5" fill="#c4cacc" />
+ <path d="m26 6h12v50h-12z" fill="#dae1e4" />
+ <path d="m27 6h10v48.94h-10z" fill="#c4cacc" />
+ <circle cx="32" cy="55" r="9" fill="#dae1e4" />
+ <g fill="#2e7de5">
+ <circle cx="32" cy="55" r="8" />
+ <path d="m27 39h10v12h-10z" />
+ </g>
+ <g fill="#fff">
+ <path d="m33 9h5v2h-5z" />
+ <path d="m33 17h5v2h-5z" />
+ <path d="m33 25h5v2h-5z" />
+ <path d="m33 33h5v2h-5z" />
+ <path d="m33 41h5v2h-5z" />
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <path fill="#F8EFE0" d="M 11.018 52.475 L 11.018 31.819 C 7.317 33.065 4.779 29.687 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 51.937 51.358 C 43.944 54.785 42.3 46.755 42.28 46.918 C 41.461 53.613 28.847 53.227 26.809 48.767 C 26.439 47.958 26.67 47.804 26.141 47.766 C 23.045 47.544 22.868 55.347 11.018 52.475 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
+ <path fill="#D93133" d="M 11.018 31.819 C 10.054 32.144 9.151 32.151 8.401 31.927 C 7.816 31.754 7.322 31.444 6.959 31.043 C 6.596 30.643 6.366 30.156 6.295 29.618 C 6.188 28.785 6.472 27.843 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 49.63 30.982 C 49.63 30.618 33.464 19.43 31.679 18.213 C 29.788 19.473 13.326 30.571 13.326 31.04 L 11.018 31.819 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
+ <path fill="#313A58" d="M 31.595 25.496 C 33.228 25.496 34.711 26.081 35.784 27.021 C 36.861 27.963 37.526 29.076 37.526 30.503 L 37.526 35.325 L 25.662 35.325 L 25.662 30.503 C 25.662 29.073 26.33 27.961 27.404 27.021 C 28.479 26.081 29.963 25.496 31.595 25.496 Z" style=""/>
+ <path fill="#ABB9BC" d="M 32.111 31.421 L 32.111 34.426 L 36.496 34.426 L 36.496 31.421 L 32.111 31.421 Z M 32.111 26.424 L 32.111 30.517 L 36.496 30.517 L 36.496 30.505 C 36.496 29.326 35.945 28.439 35.056 27.661 C 34.282 26.983 33.252 26.529 32.111 26.424 Z M 31.079 30.517 L 31.079 26.424 C 29.936 26.531 28.909 26.983 28.134 27.661 C 27.245 28.439 26.694 29.326 26.694 30.505 L 26.694 30.517 L 31.079 30.517 Z M 31.079 34.423 L 31.079 31.421 L 26.694 31.421 L 26.694 34.426 L 31.079 34.426 L 31.079 34.423 Z" style=""/>
+ <path fill="#313A58" d="M 51.92 31.732 L 49.64 30.959 L 49.64 52.389 L 51.92 52.389 L 51.92 31.732 Z M 10.908 31.819 L 13.189 31.046 L 13.189 52.476 L 10.908 52.476 L 10.908 31.819 Z" style=""/>
+ <path d="M 11.097 51.603 C 13.269 52.586 15.988 52.276 18.451 51.315 C 21.367 50.176 23.866 48.168 24.668 46.318 C 24.9 45.781 25.509 45.54 26.029 45.779 C 26.259 45.885 26.444 46.075 26.547 46.312 C 27.432 48.152 28.886 49.487 30.554 50.246 C 31.623 50.733 32.775 50.983 33.918 50.978 C 35.051 50.973 36.18 50.717 37.211 50.195 C 38.688 49.446 39.974 48.13 40.802 46.195 C 41.031 45.656 41.641 45.412 42.163 45.649 C 42.416 45.764 42.614 45.978 42.711 46.245 C 43.106 47.121 43.54 47.869 44.009 48.496 C 45.11 49.969 46.402 50.756 47.805 50.981 C 49.259 51.215 50.874 50.868 52.56 50.07 C 53.763 49.501 55 48.701 56.239 47.714 L 57.499 49.397 C 56.142 50.478 54.77 51.363 53.416 52.004 C 51.373 52.971 49.365 53.383 47.49 53.082 C 45.567 52.773 43.824 51.731 42.377 49.796 C 42.148 49.488 41.933 49.17 41.734 48.842 C 40.756 50.32 39.505 51.399 38.116 52.103 C 36.799 52.772 35.361 53.098 33.918 53.104 C 32.484 53.109 31.046 52.799 29.722 52.197 C 28.122 51.468 26.677 50.311 25.588 48.764 C 24.183 50.57 21.811 52.279 19.178 53.307 C 16.265 54.444 12.989 54.782 10.273 53.553 L 11.097 51.603 Z" style="fill: rgb(30, 130, 255);"/>
+ <path d="M 10.92 57.018 C 13.092 58.001 15.811 57.691 18.274 56.73 C 21.19 55.591 23.689 53.583 24.491 51.733 C 24.723 51.196 25.332 50.955 25.852 51.194 C 26.082 51.3 26.267 51.49 26.37 51.727 C 27.255 53.567 28.709 54.902 30.377 55.661 C 31.446 56.148 32.598 56.398 33.741 56.393 C 34.874 56.388 36.003 56.132 37.034 55.61 C 38.511 54.861 39.797 53.545 40.625 51.61 C 40.854 51.071 41.464 50.827 41.986 51.064 C 42.239 51.179 42.437 51.393 42.534 51.66 C 42.929 52.536 43.363 53.284 43.832 53.911 C 44.933 55.384 46.225 56.171 47.628 56.396 C 49.082 56.63 50.697 56.283 52.383 55.485 C 53.586 54.916 54.823 54.116 56.062 53.129 L 57.322 54.812 C 55.965 55.893 54.593 56.778 53.239 57.419 C 51.196 58.386 49.188 58.798 47.313 58.497 C 45.39 58.188 43.647 57.146 42.2 55.211 C 41.971 54.903 41.756 54.585 41.557 54.257 C 40.579 55.735 39.328 56.814 37.939 57.518 C 36.622 58.187 35.184 58.513 33.741 58.519 C 32.307 58.524 30.869 58.214 29.545 57.612 C 27.945 56.883 26.5 55.726 25.411 54.179 C 24.006 55.985 21.634 57.694 19.001 58.722 C 16.088 59.859 12.812 60.197 10.096 58.968 L 10.92 57.018 Z" style="fill: rgb(30, 130, 255);"/>
+</svg>
\ No newline at end of file
--- /dev/null
+<svg width="55" height="63" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__e">
+ <feMorphology radius="2" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__g">
+ <feMorphology radius="1.08" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__i">
+ <feMorphology radius="1.44" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__k">
+ <feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <mask id="prefix__f" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-2" y="-2"
+ width="27.056" height="36.375">
+ <path fill="#fff" d="M9 21h27.056v36.375H9z" />
+ <use xlink:href="#prefix__a" />
+ </mask>
+ <mask id="prefix__h" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.08" y="-1.08"
+ width="14.41" height="19.66">
+ <path fill="#fff" d="M2.92 3.92h14.41v19.66H2.92z" />
+ <use xlink:href="#prefix__b" />
+ </mask>
+ <mask id="prefix__j" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.44" y="-1.44"
+ width="19.505" height="26.505">
+ <path fill="#fff" d="M25.56-1.44h19.505v26.505H25.56z" />
+ <use xlink:href="#prefix__c" />
+ </mask>
+ <mask id="prefix__l" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="67"
+ height="4" fill="#fff">
+ <use xlink:href="#prefix__d" />
+ </mask>
+ <path
+ d="M22.528 23C20.887 23 11 38.241 11 44.803c0 5.174 2.987 10.572 11.528 10.572 7.82 0 11.528-5.346 11.528-10.572C34.056 38.158 24.169 23 22.528 23z"
+ id="prefix__a" />
+ <path
+ d="M10.125 5C9.253 5 4 13.238 4 16.785c0 2.797 1.587 5.715 6.125 5.715 4.155 0 6.125-2.89 6.125-5.715C16.25 13.193 10.997 5 10.125 5z"
+ id="prefix__b" />
+ <path
+ d="M35.313 0C34.129 0 27 11.122 27 15.91c0 3.776 2.154 7.715 8.313 7.715 5.64 0 8.312-3.901 8.312-7.715 0-4.849-7.129-15.91-8.313-15.91z"
+ id="prefix__c" />
+ <rect id="prefix__d" x="-8.105" y="28.395" width="67" height="4" rx="2" />
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <g transform="translate(2 2)">
+ <use fill="#000" filter="url(#prefix__e)" xlink:href="#prefix__a" />
+ <use fill-opacity=".3" fill="#55A4FF" xlink:href="#prefix__a" />
+ <use stroke="#FFF" mask="url(#prefix__f)" stroke-width="4" xlink:href="#prefix__a" />
+ </g>
+ <g transform="translate(2 2)">
+ <use fill="#000" filter="url(#prefix__g)" xlink:href="#prefix__b" />
+ <use fill-opacity=".3" fill="#55A4FF" xlink:href="#prefix__b" />
+ <use stroke="#FFF" mask="url(#prefix__h)" stroke-width="2.16" xlink:href="#prefix__b" />
+ </g>
+ <g transform="translate(2 2)">
+ <use fill="#000" filter="url(#prefix__i)" xlink:href="#prefix__c" />
+ <use fill-opacity=".3" fill="#55A4FF" xlink:href="#prefix__c" />
+ <use stroke="#FFF" mask="url(#prefix__j)" stroke-width="2.88" xlink:href="#prefix__c" />
+ </g>
+ <g transform="rotate(-45 28.81 28.981)">
+ <use fill="#000" filter="url(#prefix__k)" xlink:href="#prefix__d" />
+ <use stroke="#FFF" mask="url(#prefix__l)" stroke-width="2" fill="#464646" xlink:href="#prefix__d" />
+ </g>
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<svg width="46" height="63" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__d">
+ <feMorphology radius="2" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__f">
+ <feMorphology radius="1.08" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__h">
+ <feMorphology radius="1.44" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <path
+ d="M18.528 23C16.887 23 7 38.241 7 44.803c0 5.174 2.987 10.572 11.528 10.572 7.82 0 11.528-5.346 11.528-10.572C30.056 38.158 20.169 23 18.528 23z"
+ id="prefix__a" />
+ <path
+ d="M6.125 5C5.253 5 0 13.238 0 16.785 0 19.582 1.587 22.5 6.125 22.5c4.155 0 6.125-2.89 6.125-5.715C12.25 13.193 6.997 5 6.125 5z"
+ id="prefix__b" />
+ <path
+ d="M31.313 0C30.128 0 23 11.122 23 15.91c0 3.776 2.154 7.715 8.313 7.715 5.64 0 8.312-3.901 8.312-7.715 0-4.849-7.129-15.91-8.313-15.91z"
+ id="prefix__c" />
+ <mask id="prefix__e" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-2" y="-2"
+ width="27.056" height="36.375">
+ <path fill="#fff" d="M5 21h27.056v36.375H5z" />
+ <use xlink:href="#prefix__a" />
+ </mask>
+ <mask id="prefix__g" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.08" y="-1.08"
+ width="14.41" height="19.66">
+ <path fill="#fff" d="M-1.08 3.92h14.41v19.66H-1.08z" />
+ <use xlink:href="#prefix__b" />
+ </mask>
+ <mask id="prefix__i" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.44" y="-1.44"
+ width="19.505" height="26.505">
+ <path fill="#fff" d="M21.56-1.44h19.505v26.505H21.56z" />
+ <use xlink:href="#prefix__c" />
+ </mask>
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <g transform="translate(3 2)">
+ <use fill="#000" filter="url(#prefix__d)" xlink:href="#prefix__a" />
+ <use fill-opacity=".3" fill="#55A4FF" xlink:href="#prefix__a" />
+ <use stroke="#FFF" mask="url(#prefix__e)" stroke-width="4" xlink:href="#prefix__a" />
+ </g>
+ <g transform="translate(3 2)">
+ <use fill="#000" filter="url(#prefix__f)" xlink:href="#prefix__b" />
+ <use fill-opacity=".3" fill="#55A4FF" xlink:href="#prefix__b" />
+ <use stroke="#FFF" mask="url(#prefix__g)" stroke-width="2.16" xlink:href="#prefix__b" />
+ </g>
+ <g transform="translate(3 2)">
+ <use fill="#000" filter="url(#prefix__h)" xlink:href="#prefix__c" />
+ <use fill="#55A4FF" xlink:href="#prefix__c" />
+ <use stroke="#FFF" mask="url(#prefix__i)" stroke-width="2.88" xlink:href="#prefix__c" />
+ </g>
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<svg width="46" height="63" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__d">
+ <feMorphology radius="2" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__f">
+ <feMorphology radius="1.08" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__h">
+ <feMorphology radius="1.44" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <path
+ d="M18.528 23C16.887 23 7 38.241 7 44.803c0 5.174 2.987 10.572 11.528 10.572 7.82 0 11.528-5.346 11.528-10.572C30.056 38.158 20.169 23 18.528 23z"
+ id="prefix__a" />
+ <path
+ d="M6.125 5C5.253 5 0 13.238 0 16.785 0 19.582 1.587 22.5 6.125 22.5c4.155 0 6.125-2.89 6.125-5.715C12.25 13.193 6.997 5 6.125 5z"
+ id="prefix__b" />
+ <path
+ d="M31.313 0C30.128 0 23 11.122 23 15.91c0 3.776 2.154 7.715 8.313 7.715 5.64 0 8.312-3.901 8.312-7.715 0-4.849-7.129-15.91-8.313-15.91z"
+ id="prefix__c" />
+ <mask id="prefix__e" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-2" y="-2"
+ width="27.056" height="36.375">
+ <path fill="#fff" d="M5 21h27.056v36.375H5z" />
+ <use xlink:href="#prefix__a" />
+ </mask>
+ <mask id="prefix__g" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.08" y="-1.08"
+ width="14.41" height="19.66">
+ <path fill="#fff" d="M-1.08 3.92h14.41v19.66H-1.08z" />
+ <use xlink:href="#prefix__b" />
+ </mask>
+ <mask id="prefix__i" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.44" y="-1.44"
+ width="19.505" height="26.505">
+ <path fill="#fff" d="M21.56-1.44h19.505v26.505H21.56z" />
+ <use xlink:href="#prefix__c" />
+ </mask>
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <g transform="translate(3 2)">
+ <use fill="#000" filter="url(#prefix__d)" xlink:href="#prefix__a" />
+ <use fill-opacity=".3" fill="#55A4FF" xlink:href="#prefix__a" />
+ <use stroke="#FFF" mask="url(#prefix__e)" stroke-width="4" xlink:href="#prefix__a" />
+ </g>
+ <g transform="translate(3 2)">
+ <use fill="#000" filter="url(#prefix__f)" xlink:href="#prefix__b" />
+ <use fill="#55A4FF" xlink:href="#prefix__b" />
+ <use stroke="#FFF" mask="url(#prefix__g)" stroke-width="2.16" xlink:href="#prefix__b" />
+ </g>
+ <g transform="translate(3 2)">
+ <use fill="#000" filter="url(#prefix__h)" xlink:href="#prefix__c" />
+ <use fill="#55A4FF" xlink:href="#prefix__c" />
+ <use stroke="#FFF" mask="url(#prefix__i)" stroke-width="2.88" xlink:href="#prefix__c" />
+ </g>
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<svg width="46" height="63" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__d">
+ <feMorphology radius="2" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__f">
+ <feMorphology radius="1.08" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__h">
+ <feMorphology radius="1.44" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <path
+ d="M18.528 23C16.887 23 7 38.241 7 44.803c0 5.174 2.987 10.572 11.528 10.572 7.82 0 11.528-5.346 11.528-10.572C30.056 38.158 20.169 23 18.528 23z"
+ id="prefix__a" />
+ <path
+ d="M6.125 5C5.253 5 0 13.238 0 16.785 0 19.582 1.587 22.5 6.125 22.5c4.155 0 6.125-2.89 6.125-5.715C12.25 13.193 6.997 5 6.125 5z"
+ id="prefix__b" />
+ <path
+ d="M31.313 0C30.128 0 23 11.122 23 15.91c0 3.776 2.154 7.715 8.313 7.715 5.64 0 8.312-3.901 8.312-7.715 0-4.849-7.129-15.91-8.313-15.91z"
+ id="prefix__c" />
+ <mask id="prefix__e" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-2" y="-2"
+ width="27.056" height="36.375">
+ <path fill="#fff" d="M5 21h27.056v36.375H5z" />
+ <use xlink:href="#prefix__a" />
+ </mask>
+ <mask id="prefix__g" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.08" y="-1.08"
+ width="14.41" height="19.66">
+ <path fill="#fff" d="M-1.08 3.92h14.41v19.66H-1.08z" />
+ <use xlink:href="#prefix__b" />
+ </mask>
+ <mask id="prefix__i" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.44" y="-1.44"
+ width="19.505" height="26.505">
+ <path fill="#fff" d="M21.56-1.44h19.505v26.505H21.56z" />
+ <use xlink:href="#prefix__c" />
+ </mask>
+ </defs>
+ <g fill="none" fill-rule="evenodd">
+ <g transform="translate(3 2)">
+ <use fill="#000" filter="url(#prefix__d)" xlink:href="#prefix__a" />
+ <use fill="#55A4FF" xlink:href="#prefix__a" />
+ <use stroke="#FFF" mask="url(#prefix__e)" stroke-width="4" xlink:href="#prefix__a" />
+ </g>
+ <g transform="translate(3 2)">
+ <use fill="#000" filter="url(#prefix__f)" xlink:href="#prefix__b" />
+ <use fill="#55A4FF" xlink:href="#prefix__b" />
+ <use stroke="#FFF" mask="url(#prefix__g)" stroke-width="2.16" xlink:href="#prefix__b" />
+ </g>
+ <g transform="translate(3 2)">
+ <use fill="#000" filter="url(#prefix__h)" xlink:href="#prefix__c" />
+ <use fill="#55A4FF" xlink:href="#prefix__c" />
+ <use stroke="#FFF" mask="url(#prefix__i)" stroke-width="2.88" xlink:href="#prefix__c" />
+ </g>
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="55" height="63">
+ <defs>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__e">
+ <feMorphology radius="2" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1.5" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__g">
+ <feMorphology radius="1.08" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="prefix__i">
+ <feMorphology radius="1.44" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1" />
+ <feOffset dy="1" in="shadowSpreadOuter1" result="shadowOffsetOuter1" />
+ <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
+ <feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1" />
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" in="shadowBlurOuter1" />
+ </filter>
+ <path
+ d="M22.528 23C20.887 23 11 38.241 11 44.803c0 5.174 2.987 10.572 11.528 10.572 7.82 0 11.528-5.346 11.528-10.572C34.056 38.158 24.169 23 22.528 23z"
+ id="prefix__a" />
+ <path
+ d="M10.125 5C9.253 5 4 13.238 4 16.785c0 2.797 1.587 5.715 6.125 5.715 4.155 0 6.125-2.89 6.125-5.715C16.25 13.193 10.997 5 10.125 5z"
+ id="prefix__b" />
+ <path
+ d="M35.313 0C34.129 0 27 11.122 27 15.91c0 3.776 2.154 7.715 8.313 7.715 5.64 0 8.312-3.901 8.312-7.715 0-4.849-7.129-15.91-8.313-15.91z"
+ id="prefix__c" />
+ <mask id="prefix__f" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-2" y="-2" width="27.056"
+ height="36.375">
+ <path fill="#fff" d="M9 21h27.056v36.375H9z" />
+ <use xlink:href="#prefix__a" />
+ </mask>
+ <mask id="prefix__h" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.08" y="-1.08"
+ width="14.41" height="19.66">
+ <path fill="#fff" d="M2.92 3.92h14.41v19.66H2.92z" />
+ <use xlink:href="#prefix__b" />
+ </mask>
+ <mask id="prefix__j" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-1.44" y="-1.44"
+ width="19.505" height="26.505">
+ <path fill="#fff" d="M25.56-1.44h19.505v26.505H25.56z" />
+ <use xlink:href="#prefix__c" />
+ </mask>
+ <rect id="prefix__d" x="-8.105" y="28.395" width="67" height="4" rx="2" />
+ </defs>
+ <g transform="translate(2 2)" fill="none" fill-rule="evenodd">
+ <use height="100%" width="100%" xlink:href="#prefix__a" fill="#000" filter="url(#prefix__e)" />
+ <use height="100%" width="100%" xlink:href="#prefix__a" fill="#55a4ff" fill-opacity=".3" />
+ <use height="100%" width="100%" xlink:href="#prefix__a" mask="url(#prefix__f)" stroke="#fff" stroke-width="4" />
+ </g>
+ <g transform="translate(2 2)" fill="none" fill-rule="evenodd">
+ <use height="100%" width="100%" xlink:href="#prefix__b" fill="#000" filter="url(#prefix__g)" />
+ <use height="100%" width="100%" xlink:href="#prefix__b" fill="#55a4ff" fill-opacity=".3" />
+ <use height="100%" width="100%" xlink:href="#prefix__b" mask="url(#prefix__h)" stroke="#fff"
+ stroke-width="2.16" />
+ </g>
+ <g transform="translate(2 2)" fill="none" fill-rule="evenodd">
+ <use height="100%" width="100%" xlink:href="#prefix__c" fill="#000" filter="url(#prefix__i)" />
+ <use height="100%" width="100%" xlink:href="#prefix__c" fill="#55a4ff" fill-opacity=".3" />
+ <use height="100%" width="100%" xlink:href="#prefix__c" mask="url(#prefix__j)" stroke="#fff"
+ stroke-width="2.88" />
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" height="600" width="600" data-name="Calque 1">
+ <path fill="#005892" d="M0 0h600v600H0z" />
+ <rect x="220.481" y="111.57" width="159.038" height="159.038" rx="12.759" ry="12.759" fill="#fff" />
+ <path fill="#005891" d="M334.557 134.05l17.013 17.697-24.152 6.152z" />
+ <path
+ d="M357.95 191.089a57.646 57.646 0 00-10.178-32.81l-5.164 1.974a56.05 56.05 0 0110.253 30.836 53.165 53.165 0 01-45.57 52.329 210.152 210.152 0 01-1.747-104.81 55.443 55.443 0 0119.747 6l1.291-4.861a57.57 57.57 0 00-19.747-6.152 150.684 150.684 0 018.127-22.025h-7.595a164.05 164.05 0 00-7.595 21.645 57.95 57.95 0 000 115.823h1.975c1.975 7.063 4.253 14.278 7.063 21.646h7.063c-2.886-7.595-5.392-15.19-7.595-22.254a57.95 57.95 0 0049.671-57.341z"
+ fill="#005891" />
+ <path d="M298.633 130.405h-7.063" fill="#fff" />
+ <g fill="#fff">
+ <path
+ d="M123.418 315.342h22.025l14.582 44.126 14.05-44.126h22.102l7.975 76.48H182.05l-3.266-38.278-11.317 38.279h-15.873l-11.317-38.279-4.48 38.279H114zM268.405 372.608h-34.709v-10.254h26.279V346.33H233.24v-11.544h35.164v-19.443h-56.278v76.48h56.278zM403.975 372.608H369.19v-10.254h26.278V346.33h-26.734v-11.544h35.24v-19.443H347.62v76.48h56.355zM297.038 391.823h21.19v-57.038h18.76v-19.443h-59.165v19.443h19.215zM448.101 314.658a37.975 37.975 0 1037.975 37.975 37.975 37.975 0 00-37.975-37.975zm0 57.494a19.443 19.443 0 1119.443-19.443 19.443 19.443 0 01-19.443 19.443zM134.962 464.127h23.696v-14.81h-23.696v-14.963h30.684v-18.607H114v72.607h20.962zM213.57 458.81s10.936-1.215 10.936-21.19a19.519 19.519 0 00-18.835-21.873h-34.86v72.607h17.695V461.62h6.532l11.165 26.734h20.886zm-11.848-11.544h-13.52v-17.469h13.52a9.494 9.494 0 010 17.469zM274.025 415.747h-16.253l-27.418 72.607h20.735l5.392-13.519h19.975l4.557 13.52h19.822zm-15.19 45.114l6.988-19.52 6.987 19.52zM321.494 449.316l26.05 39.038h16.785v-72.607h-18.911v42.456l-24.152-42.456h-18.38v72.607h18.608zM418.253 465.038a18.38 18.38 0 11-.987-26.43l11.848-13.292a36.076 36.076 0 100 53.773zM486 470.127h-33.038v-9.722h24.987V445.14h-25.443v-10.936H486V415.67h-53.544v72.76H486z" />
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
+ <path
+ d="m32 2.5c.98 0 1.76.79 1.76 1.76v8.25l2.82-4.09c.35-.5.9-.77 1.47-.76.34 0 .68.11.98.31.8.55 1.01 1.65.45 2.45l-5.73 8.31v3.56 6.66l8.85-5.11 4.33-9.11c.42-.88 1.47-1.25 2.35-.84.33.16.59.4.76.7.29.49.33 1.1.07 1.65l-2.13 4.49 7.15-4.13c.85-.49 1.92-.2 2.41.65.49.85.2 1.92-.65 2.41l-7.15 4.13 4.96.4c.61.05 1.12.4 1.4.89.17.3.25.64.22 1.01-.08.97-.92 1.69-1.9 1.62l-10.06-.8-8.84 5.09 5.77 3.33 3.08 1.78 10.06-.8c.97-.08 1.82.64 1.9 1.62.03.36-.05.71-.22 1.01-.28.49-.79.84-1.4.89l-4.96.4 7.15 4.13c.85.49 1.13 1.56.65 2.41-.49.85-1.56 1.13-2.41.64l-7.15-4.13 2.13 4.49c.26.55.22 1.17-.07 1.65-.17.29-.43.54-.76.69-.88.42-1.93.05-2.35-.83l-4.33-9.11-8.85-5.11v6.66 3.56l5.73 8.31c.55.8.35 1.9-.45 2.45-.3.21-.64.31-.98.31-.57.01-1.12-.26-1.47-.76l-2.82-4.09v8.25c0 .98-.79 1.76-1.76 1.76-.98 0-1.76-.79-1.76-1.76v-8.25l-2.82 4.09c-.35.5-.9.77-1.47.76-.34 0-.68-.11-.98-.31-.8-.55-1.01-1.65-.45-2.45l5.73-8.31v-3.56-6.66l-5.77 3.33-3.08 1.78-4.33 9.11c-.42.88-1.47 1.25-2.35.83-.33-.16-.59-.4-.76-.69-.29-.49-.33-1.1-.07-1.65l2.14-4.49-7.15 4.13c-.85.49-1.92.2-2.41-.64-.49-.85-.2-1.92.64-2.41l7.15-4.13-4.96-.4c-.61-.05-1.12-.4-1.4-.89-.17-.3-.25-.64-.22-1.01.08-.97.92-1.69 1.9-1.62l10.06.8 3.08-1.78 5.75-3.33-8.85-5.11-10.06.8c-.97.08-1.82-.64-1.9-1.62-.03-.36.05-.71.22-1.01.28-.49.79-.84 1.4-.89l4.96-.4-7.15-4.11c-.85-.49-1.13-1.56-.64-2.41.49-.85 1.56-1.13 2.41-.65l7.15 4.13-2.14-4.49c-.26-.55-.22-1.17.07-1.65.17-.29.43-.54.76-.7.88-.42 1.93-.05 2.35.84l4.33 9.11 8.85 5.11v-6.66-3.56l-5.73-8.31c-.55-.8-.35-1.9.45-2.45.3-.21.64-.31.98-.31.57-.01 1.12.26 1.47.76l2.82 4.09v-8.25c.01-.97.79-1.76 1.77-1.76"
+ fill="#dae1e4" />
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <g transform="matrix(0.109429, 0, 0, 0.095795, 3.683853, 5.87504)" style="">
+ <polygon style="fill:#FFDA44;" points="225.584 244.867 174.304 380.884 268.543 380.884 209.837 509.421 367.316 333.616 271.782 333.616 303.985 244.867"/>
+ <polygon style="fill:#CCA400;" points="304.519 244.867 226.118 244.867 207.482 294.3 286.581 294.3"/>
+ <path style="fill:#B8D6FD;" d="M 459.559 266.555 C 488.522 266.555 512.001 243.077 512.001 214.113 C 512.001 185.149 488.523 161.671 459.559 161.671 C 450.829 161.671 442.605 163.816 435.364 167.589 C 428.157 153.316 416.099 141.917 401.341 135.574 C 401.341 135.443 401.351 135.316 401.351 135.185 C 401.351 62.632 342.535 3.817 269.982 3.817 C 209.899 3.817 159.273 44.169 143.634 99.239 C 109.041 105.309 81.724 132.452 75.398 166.956 C 68.464 163.574 60.675 161.671 52.44 161.671 C 23.479 161.672 0 185.15 0 214.114 C 0 243.078 23.479 266.556 52.442 266.556 L 459.559 266.556 L 459.559 266.555 Z"/>
+ <path style="opacity:0.41;fill:#6AB3EA;enable-background:new ;" d="M 458.404 160.434 C 449.674 160.434 441.45 162.579 434.209 166.352 C 427.002 152.079 414.944 140.68 400.186 134.337 C 400.186 134.206 400.196 134.079 400.196 133.948 C 400.196 61.395 341.38 2.58 268.827 2.58 C 257.171 2.58 245.875 4.105 235.117 6.955 C 291.333 21.84 332.772 73.052 332.772 133.95 C 332.772 134.081 332.763 134.208 332.762 134.339 C 347.519 140.681 359.578 152.081 366.785 166.354 C 374.026 162.58 382.25 160.436 390.98 160.436 C 419.943 160.436 443.422 183.914 443.422 212.878 C 443.422 241.841 419.944 265.32 390.98 265.32 L 458.404 265.32 C 487.367 265.32 510.846 241.841 510.846 212.878 C 510.846 183.912 487.367 160.434 458.404 160.434 Z"/>
+ <g style="opacity:0.41;">
+ <path style="fill:#6AB3EA;" d="M258.252,34.812c0,3.364-2.216,6.456-5.612,7.421c-40.109,11.389-68.121,48.482-68.121,90.201 c0,4.264-3.455,7.718-7.718,7.718s-7.718-3.455-7.718-7.718c0-48.587,32.626-91.785,79.341-105.052 c4.1-1.165,8.369,1.216,9.534,5.316C258.157,33.404,258.252,34.114,258.252,34.812z"/>
+ </g>
+ </g>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <path fill="#F8EFE0" d="M 11.018 52.475 L 11.018 31.819 C 7.317 33.065 4.779 29.687 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 51.937 51.358 C 43.944 54.785 42.3 46.755 42.28 46.918 C 41.461 53.613 28.847 53.227 26.809 48.767 C 26.439 47.958 26.67 47.804 26.141 47.766 C 23.045 47.544 22.868 55.347 11.018 52.475 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
+ <path fill="#D93133" d="M 11.018 31.819 C 10.054 32.144 9.151 32.151 8.401 31.927 C 7.816 31.754 7.322 31.444 6.959 31.043 C 6.596 30.643 6.366 30.156 6.295 29.618 C 6.188 28.785 6.472 27.843 7.284 26.959 C 7.325 26.916 7.371 26.873 7.425 26.837 L 30.938 10.768 C 31.242 10.522 31.712 10.497 32.05 10.727 L 55.617 26.768 C 55.654 26.793 55.688 26.819 55.72 26.851 C 56.812 27.879 57.084 29.019 56.82 29.983 C 56.692 30.449 56.434 30.88 56.071 31.238 C 55.708 31.596 55.249 31.867 54.735 32.029 C 53.911 32.288 52.931 32.281 51.937 31.869 L 49.63 30.982 C 49.63 30.618 33.464 19.43 31.679 18.213 C 29.788 19.473 13.326 30.571 13.326 31.04 L 11.018 31.819 Z M 51.987 12.422 L 51.987 20.469 L 44.911 16.382 L 44.911 12.422 L 51.987 12.422 Z" style=""/>
+ <path fill="#313A58" d="M 31.595 25.496 C 33.228 25.496 34.711 26.081 35.784 27.021 C 36.861 27.963 37.526 29.076 37.526 30.503 L 37.526 35.325 L 25.662 35.325 L 25.662 30.503 C 25.662 29.073 26.33 27.961 27.404 27.021 C 28.479 26.081 29.963 25.496 31.595 25.496 Z" style=""/>
+ <path fill="#ABB9BC" d="M 32.111 31.421 L 32.111 34.426 L 36.496 34.426 L 36.496 31.421 L 32.111 31.421 Z M 32.111 26.424 L 32.111 30.517 L 36.496 30.517 L 36.496 30.505 C 36.496 29.326 35.945 28.439 35.056 27.661 C 34.282 26.983 33.252 26.529 32.111 26.424 Z M 31.079 30.517 L 31.079 26.424 C 29.936 26.531 28.909 26.983 28.134 27.661 C 27.245 28.439 26.694 29.326 26.694 30.505 L 26.694 30.517 L 31.079 30.517 Z M 31.079 34.423 L 31.079 31.421 L 26.694 31.421 L 26.694 34.426 L 31.079 34.426 L 31.079 34.423 Z" style=""/>
+ <path fill="#313A58" d="M 51.92 31.732 L 49.64 30.959 L 49.64 52.389 L 51.92 52.389 L 51.92 31.732 Z M 10.908 31.819 L 13.189 31.046 L 13.189 52.476 L 10.908 52.476 L 10.908 31.819 Z" style=""/>
+ <path d="M 11.097 51.603 C 13.269 52.586 15.988 52.276 18.451 51.315 C 21.367 50.176 23.866 48.168 24.668 46.318 C 24.9 45.781 25.509 45.54 26.029 45.779 C 26.259 45.885 26.444 46.075 26.547 46.312 C 27.432 48.152 28.886 49.487 30.554 50.246 C 31.623 50.733 32.775 50.983 33.918 50.978 C 35.051 50.973 36.18 50.717 37.211 50.195 C 38.688 49.446 39.974 48.13 40.802 46.195 C 41.031 45.656 41.641 45.412 42.163 45.649 C 42.416 45.764 42.614 45.978 42.711 46.245 C 43.106 47.121 43.54 47.869 44.009 48.496 C 45.11 49.969 46.402 50.756 47.805 50.981 C 49.259 51.215 50.874 50.868 52.56 50.07 C 53.763 49.501 55 48.701 56.239 47.714 L 57.499 49.397 C 56.142 50.478 54.77 51.363 53.416 52.004 C 51.373 52.971 49.365 53.383 47.49 53.082 C 45.567 52.773 43.824 51.731 42.377 49.796 C 42.148 49.488 41.933 49.17 41.734 48.842 C 40.756 50.32 39.505 51.399 38.116 52.103 C 36.799 52.772 35.361 53.098 33.918 53.104 C 32.484 53.109 31.046 52.799 29.722 52.197 C 28.122 51.468 26.677 50.311 25.588 48.764 C 24.183 50.57 21.811 52.279 19.178 53.307 C 16.265 54.444 12.989 54.782 10.273 53.553 L 11.097 51.603 Z" style="fill: rgb(30, 130, 255);"/>
+ <path d="M 8.218 34.7 C 8.218 34.7 8.173 34.7 8.13 34.7 C 8.041 34.7 7.997 34.7 7.953 34.64 L 7.908 34.64 C 6.888 34.399 6.046 33.017 5.958 31.515 L 5.958 31.034 C 6.003 30.794 6.046 30.494 6.091 30.192 C 6.18 30.013 6.268 29.772 6.357 29.532 L 6.667 28.93 C 7.376 27.789 7.953 26.648 8.351 25.445 C 8.794 26.888 9.504 28.15 10.08 29.111 C 10.124 29.231 10.213 29.411 10.346 29.592 C 10.434 29.832 10.567 30.133 10.701 30.373 C 10.745 30.553 10.789 30.854 10.834 31.094 L 10.834 31.455 C 10.834 31.515 10.834 31.575 10.834 31.635 C 10.834 31.635 10.834 31.695 10.834 31.695 L 10.834 31.756 L 10.834 31.815 C 10.701 33.138 9.903 34.399 8.928 34.64 L 8.883 34.64 C 8.839 34.64 8.794 34.7 8.706 34.7 C 8.661 34.7 8.618 34.7 8.618 34.7 L 8.218 34.7" fill="#1e82ff" style=""/>
+ <path d="M 17.152 21.924 C 17.152 21.924 17.107 21.924 17.064 21.924 C 16.975 21.924 16.931 21.924 16.887 21.864 L 16.842 21.864 C 15.822 21.623 14.98 20.241 14.892 18.739 L 14.892 18.258 C 14.937 18.018 14.98 17.718 15.025 17.416 C 15.114 17.237 15.202 16.996 15.291 16.756 L 15.601 16.154 C 16.31 15.013 16.887 13.872 17.285 12.669 C 17.728 14.112 18.438 15.374 19.014 16.335 C 19.058 16.455 19.147 16.635 19.28 16.816 C 19.368 17.056 19.501 17.357 19.635 17.597 C 19.679 17.777 19.723 18.078 19.768 18.318 L 19.768 18.679 C 19.768 18.739 19.768 18.799 19.768 18.859 C 19.768 18.859 19.768 18.919 19.768 18.919 L 19.768 18.98 L 19.768 19.039 C 19.635 20.362 18.837 21.623 17.862 21.864 L 17.817 21.864 C 17.773 21.864 17.728 21.924 17.64 21.924 C 17.595 21.924 17.552 21.924 17.552 21.924 L 17.152 21.924" fill="#1e82ff" style=""/>
+ <path d="M 42.51 27.949 C 42.51 27.949 42.465 27.949 42.422 27.949 C 42.333 27.949 42.289 27.949 42.245 27.889 L 42.2 27.889 C 41.18 27.648 40.338 26.266 40.25 24.764 L 40.25 24.283 C 40.295 24.043 40.338 23.743 40.383 23.441 C 40.472 23.262 40.56 23.021 40.649 22.781 L 40.959 22.179 C 41.668 21.038 42.245 19.897 42.643 18.694 C 43.086 20.137 43.796 21.399 44.372 22.36 C 44.416 22.48 44.505 22.66 44.638 22.841 C 44.726 23.081 44.859 23.382 44.993 23.622 C 45.037 23.802 45.081 24.103 45.126 24.343 L 45.126 24.704 C 45.126 24.764 45.126 24.824 45.126 24.884 C 45.126 24.884 45.126 24.944 45.126 24.944 L 45.126 25.005 L 45.126 25.064 C 44.993 26.387 44.195 27.648 43.22 27.889 L 43.175 27.889 C 43.131 27.889 43.086 27.949 42.998 27.949 C 42.953 27.949 42.91 27.949 42.91 27.949 L 42.51 27.949" fill="#1e82ff" style=""/>
+ <path d="M 30.168 12.518 C 30.168 12.518 30.123 12.518 30.08 12.518 C 29.991 12.518 29.947 12.518 29.903 12.458 L 29.858 12.458 C 28.838 12.217 27.996 10.835 27.908 9.333 L 27.908 8.852 C 27.953 8.612 27.996 8.312 28.041 8.01 C 28.13 7.831 28.218 7.59 28.307 7.35 L 28.617 6.748 C 29.326 5.607 29.903 4.466 30.301 3.263 C 30.744 4.706 31.454 5.968 32.03 6.929 C 32.074 7.049 32.163 7.229 32.296 7.41 C 32.384 7.65 32.517 7.951 32.651 8.191 C 32.695 8.371 32.739 8.672 32.784 8.912 L 32.784 9.273 C 32.784 9.333 32.784 9.393 32.784 9.453 C 32.784 9.453 32.784 9.513 32.784 9.513 L 32.784 9.574 L 32.784 9.633 C 32.651 10.956 31.853 12.217 30.878 12.458 L 30.833 12.458 C 30.789 12.458 30.744 12.518 30.656 12.518 C 30.611 12.518 30.568 12.518 30.568 12.518 L 30.168 12.518" fill="#1e82ff" style=""/>
+ <path d="M 54.328 36.78 C 54.328 36.78 54.283 36.78 54.24 36.78 C 54.151 36.78 54.107 36.78 54.063 36.72 L 54.018 36.72 C 52.998 36.479 52.156 35.097 52.068 33.595 L 52.068 33.114 C 52.113 32.874 52.156 32.574 52.201 32.272 C 52.29 32.093 52.378 31.852 52.467 31.612 L 52.777 31.01 C 53.486 29.869 54.063 28.728 54.461 27.525 C 54.904 28.968 55.614 30.23 56.19 31.191 C 56.234 31.311 56.323 31.491 56.456 31.672 C 56.544 31.912 56.677 32.213 56.811 32.453 C 56.855 32.633 56.899 32.934 56.944 33.174 L 56.944 33.535 C 56.944 33.595 56.944 33.655 56.944 33.715 C 56.944 33.715 56.944 33.775 56.944 33.775 L 56.944 33.836 L 56.944 33.895 C 56.811 35.218 56.013 36.479 55.038 36.72 L 54.993 36.72 C 54.949 36.72 54.904 36.78 54.816 36.78 C 54.771 36.78 54.728 36.78 54.728 36.78 L 54.328 36.78" fill="#1e82ff" style=""/>
+ <path d="M 10.92 57.018 C 13.092 58.001 15.811 57.691 18.274 56.73 C 21.19 55.591 23.689 53.583 24.491 51.733 C 24.723 51.196 25.332 50.955 25.852 51.194 C 26.082 51.3 26.267 51.49 26.37 51.727 C 27.255 53.567 28.709 54.902 30.377 55.661 C 31.446 56.148 32.598 56.398 33.741 56.393 C 34.874 56.388 36.003 56.132 37.034 55.61 C 38.511 54.861 39.797 53.545 40.625 51.61 C 40.854 51.071 41.464 50.827 41.986 51.064 C 42.239 51.179 42.437 51.393 42.534 51.66 C 42.929 52.536 43.363 53.284 43.832 53.911 C 44.933 55.384 46.225 56.171 47.628 56.396 C 49.082 56.63 50.697 56.283 52.383 55.485 C 53.586 54.916 54.823 54.116 56.062 53.129 L 57.322 54.812 C 55.965 55.893 54.593 56.778 53.239 57.419 C 51.196 58.386 49.188 58.798 47.313 58.497 C 45.39 58.188 43.647 57.146 42.2 55.211 C 41.971 54.903 41.756 54.585 41.557 54.257 C 40.579 55.735 39.328 56.814 37.939 57.518 C 36.622 58.187 35.184 58.513 33.741 58.519 C 32.307 58.524 30.869 58.214 29.545 57.612 C 27.945 56.883 26.5 55.726 25.411 54.179 C 24.006 55.985 21.634 57.694 19.001 58.722 C 16.088 59.859 12.812 60.197 10.096 58.968 L 10.92 57.018 Z" style="fill: rgb(30, 130, 255);"/>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30"/>
+ <path d="M 10.382 37.307 C 12.554 38.29 15.273 37.98 17.736 37.019 C 20.652 35.88 23.151 33.872 23.953 32.022 C 24.185 31.485 24.794 31.244 25.314 31.483 C 25.544 31.589 25.729 31.779 25.832 32.016 C 26.717 33.856 28.171 35.191 29.839 35.95 C 30.908 36.437 32.06 36.687 33.203 36.682 C 34.336 36.677 35.465 36.421 36.496 35.899 C 37.973 35.15 39.259 33.834 40.087 31.899 C 40.316 31.36 40.926 31.116 41.448 31.353 C 41.701 31.468 41.899 31.682 41.996 31.949 C 42.391 32.825 42.825 33.573 43.294 34.2 C 44.395 35.673 45.687 36.46 47.09 36.685 C 48.544 36.919 50.159 36.572 51.845 35.774 C 53.048 35.205 54.285 34.405 55.524 33.418 L 56.784 35.101 C 55.427 36.182 54.055 37.067 52.701 37.708 C 50.658 38.675 48.65 39.087 46.775 38.786 C 44.852 38.477 43.109 37.435 41.662 35.5 C 41.433 35.192 41.218 34.874 41.019 34.546 C 40.041 36.024 38.79 37.103 37.401 37.807 C 36.084 38.476 34.646 38.802 33.203 38.808 C 31.769 38.813 30.331 38.503 29.007 37.901 C 27.407 37.172 25.962 36.015 24.873 34.468 C 23.468 36.274 21.096 37.983 18.463 39.011 C 15.55 40.148 12.274 40.486 9.558 39.257 L 10.382 37.307 Z" style="fill: rgb(30, 130, 255);"/>
+ <path d="M 10.205 42.722 C 12.377 43.705 15.096 43.395 17.559 42.434 C 20.475 41.295 22.974 39.287 23.776 37.437 C 24.008 36.9 24.617 36.659 25.137 36.898 C 25.367 37.004 25.552 37.194 25.655 37.431 C 26.54 39.271 27.994 40.606 29.662 41.365 C 30.731 41.852 31.883 42.102 33.026 42.097 C 34.159 42.092 35.288 41.836 36.319 41.314 C 37.796 40.565 39.082 39.249 39.91 37.314 C 40.139 36.775 40.749 36.531 41.271 36.768 C 41.524 36.883 41.722 37.097 41.819 37.364 C 42.214 38.24 42.648 38.988 43.117 39.615 C 44.218 41.088 45.51 41.875 46.913 42.1 C 48.367 42.334 49.982 41.987 51.668 41.189 C 52.871 40.62 54.108 39.82 55.347 38.833 L 56.607 40.516 C 55.25 41.597 53.878 42.482 52.524 43.123 C 50.481 44.09 48.473 44.502 46.598 44.201 C 44.675 43.892 42.932 42.85 41.485 40.915 C 41.256 40.607 41.041 40.289 40.842 39.961 C 39.864 41.439 38.613 42.518 37.224 43.222 C 35.907 43.891 34.469 44.217 33.026 44.223 C 31.592 44.228 30.154 43.918 28.83 43.316 C 27.23 42.587 25.785 41.43 24.696 39.883 C 23.291 41.689 20.919 43.398 18.286 44.426 C 15.373 45.563 12.097 45.901 9.381 44.672 L 10.205 42.722 Z" style="fill: rgb(30, 130, 255);"/>
+ <path d="M 32.307 33.157 C 30.008 33.038 27.346 31.638 25.776 29.76 C 25.48 29.421 25.206 29.064 24.956 28.688 C 23.585 30.561 21.153 32.357 18.438 33.424 C 15.546 34.563 12.297 34.903 9.61 33.677 L 10.301 32.03 C 12.342 32.962 14.845 32.775 17.183 31.979 C 17.253 28.669 18.202 25.534 19.838 22.875 C 21.336 20.442 23.646 18.223 26.281 16.786 C 29.429 15.07 33.861 14.165 36.905 16.582 C 40.064 19.088 39.596 23.333 36.462 25.669 C 35.744 26.203 34.894 26.543 34.027 26.631 C 33.319 26.702 32.602 26.606 31.934 26.309 C 31.263 26.011 30.648 25.518 30.154 24.801 C 29.581 23.968 29.17 22.827 29.031 21.336 C 28.992 20.904 29.296 20.523 29.711 20.48 C 30.125 20.44 30.493 20.757 30.532 21.188 C 30.643 22.376 30.953 23.26 31.383 23.885 C 31.708 24.357 32.102 24.676 32.525 24.866 C 32.954 25.056 33.42 25.116 33.885 25.069 C 34.48 25.009 35.072 24.769 35.582 24.39 C 37.883 22.674 38.346 19.7 35.99 17.83 C 26.886 12.683 22.711 27.316 31.469 31.199 C 32.079 31.342 32.703 31.412 33.329 31.411 C 34.495 31.407 35.656 31.142 36.717 30.6 C 38.239 29.821 39.562 28.459 40.413 26.455 C 40.605 26 41.116 25.793 41.554 25.994 C 41.766 26.091 41.931 26.272 42.013 26.498 C 42.418 27.404 42.863 28.177 43.343 28.823 C 44.48 30.357 45.818 31.177 47.274 31.413 C 48.771 31.655 50.429 31.298 52.154 30.475 C 53.379 29.893 54.635 29.073 55.89 28.065 L 56.947 29.488 C 55.592 30.576 54.222 31.465 52.872 32.109 C 50.847 33.075 48.86 33.487 47.01 33.188 C 45.117 32.881 43.402 31.847 41.976 29.924 C 41.694 29.542 41.434 29.145 41.197 28.733 C 40.211 30.324 38.919 31.474 37.476 32.212 C 36.175 32.876 34.753 33.201 33.329 33.207 C 32.988 33.209 32.647 33.192 32.307 33.157 Z" style="fill: rgb(30, 130, 255);"/>
+</svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
+ <ellipse style="stroke-width: 0px; stroke: rgb(0, 0, 0); fill:#3d3c3c;" cx="32" cy="32" rx="30" ry="30" />
+ <path
+ d="m61.55 22.14c-3.06-.84-7.3-2.16-9.33-3.51-3.39-2.25-4.77-2.26-7.12-3.02-2.35-.76-4.78-2.08-4.78-2.08s-2.57-2.17-6.5-2.77c-3.92-.6-5.65-2.61-5.65-2.61s-.6-1.38-2.2-1.96c-2.54-1.01-6.25 2.29-8.28 7.38-2.03 5.09-1.61 10.04.94 11.05 0 0 6.32 2.52 10.66 2.08 4.34-.44 7.8.39 7.8.39s3.64.85 7.37.58c3.72-.27 6.09.62 6.09.62s2.41.67 10.18.27c.31-.43.57-.91.77-1.43.67-1.69.64-3.47.05-4.99z"
+ fill="#db5336" stroke="#db5336" stroke-miterlimit="10" />
+ <ellipse transform="matrix(-.929-.37.37-.929 37.3113 37.9507)" cx="22.3" cy="15.4" rx="4.96" ry="9.92"
+ fill="#ca2a14" />
+ <g fill="#fff">
+ <path
+ d="m61.55 22.14c-1.77-.48-3.92-1.13-5.82-1.84.77 1.74.88 3.69.16 5.5-.46 1.15-1.2 2.1-2.12 2.84 1.58.07 3.84.09 6.97-.07.31-.43.57-.91.77-1.43.66-1.7.63-3.48.04-5" />
+ <path
+ d="m50.1 17.36c-1.98-1.03-3.21-1.17-5-1.75-.5-.16-1.01-.35-1.49-.54 1.27 2.47 1.49 5.53.35 8.41-.67 1.68-1.73 3.09-3.01 4.15 1.08.08 2.29.12 3.51.03 1.07-.08 2.02-.06 2.84.01 1.21-.93 2.19-2.2 2.8-3.73.89-2.21.82-4.56 0-6.58" />
+ <path
+ d="m37.81 12c-1.06-.5-2.42-1-3.99-1.24-.84-.13-1.57-.32-2.22-.54 1.6 2.52 1.73 6.77.05 10.99-.89 2.24-2.16 4.14-3.59 5.53.42 0 .83-.01 1.23-.05 1.8-.18 3.45-.15 4.76-.04 1.75-1.09 3.32-2.98 4.29-5.4 1.4-3.53 1.1-7.14-.53-9.25" />
+ <path
+ d="m24.53 15.02c-1.09 2.73-1.32 5.44-.8 7.43 1.21-1.31 2.34-3.11 3.18-5.22 1.08-2.72 1.47-5.4 1.2-7.46-1.4 1.19-2.7 3.02-3.58 5.25" />
+ </g>
+ <g fill="none" stroke="#1a171b" stroke-miterlimit="10">
+ <path d="m13.55 10.5 4.7 2.19" />
+ <path d="m13.55 10.5 13.28-3.87" />
+ <path d="m13.55 10.5 8.74 13.45" />
+ <path d="M 13.55,10.5 7,9" />
+ </g>
+ <path d="M4.5,59.5V9c0-1.38,1.12-2.5,2.5-2.5S9.5,7.62,9.5,9c0,1.21-0.86,2.22-2,2.45V59.5H4.5z" fill="#8b96ac" />
+ <path
+ d="m7 7c1.1 0 2 0.9 2 2s-0.9 2-2 2v48h-2v-50c0-1.1 0.9-2 2-2m0-1c-1.65 0-3 1.35-3 3v51h4v-48.17c1.16-0.41 2-1.52 2-2.83 0-1.65-1.35-3-3-3z"
+ fill="#676b72" />
+</svg>
\ No newline at end of file
<module>org.openhab.binding.mecmeter</module>
<module>org.openhab.binding.melcloud</module>
<module>org.openhab.binding.mercedesme</module>
- <module>org.openhab.binding.meteoalerte</module>
<module>org.openhab.binding.meteoblue</module>
+ <module>org.openhab.binding.meteofrance</module>
<module>org.openhab.binding.meteostick</module>
<module>org.openhab.binding.mffan</module>
<module>org.openhab.binding.miele</module>