Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[meteoalerte] Météo Alerte binding #7200

Merged
merged 16 commits into from
May 30, 2020
14 changes: 5 additions & 9 deletions bundles/org.openhab.binding.meteoalerte/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ The Meteo Alerte binding gives alert level regarding major weather related risk

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.

## Discovery

This binding does not handle auto-discovery.
Of course, you can add multiple things, e.g. for getting alerts for different locations.

## Binding Configuration

Expand All @@ -20,10 +16,10 @@ The binding has no configuration options, all configuration is done at Thing lev

The thing has a few configuration parameters:

| Parameter | Description |
|------------|---------------------------------------------------------------------|
| department | Name of the department. |
| refresh | Refresh interval in hours. Optional, the default value is 24 hours. |
| Parameter | Description |
|---------------|----------------------------------------------------------------------------------------|
| `department` | Name of the department. |
| refresh | Refresh interval in minutes. Optional, the default value is 1440 minutes (once a day). |

## Channels

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@
@NonNullByDefault
public class MeteoAlerteConfiguration {
public String department = "";
public Integer refresh = 24;
public Integer refresh = 1400;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1440

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import static org.openhab.binding.meteoalerte.internal.MeteoAlerteBindingConstants.*;

import java.time.ZonedDateTime;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.i18n.TimeZoneProvider;
Expand All @@ -27,6 +29,10 @@
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.
Expand All @@ -36,13 +42,17 @@
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.meteoalerte")
@NonNullByDefault
public class MeteoAlerteHandlerFactory extends BaseThingHandlerFactory {

private final Gson gson;
// Needed for converting UTC time to local time
private final TimeZoneProvider timeZoneProvider;

@Activate
public MeteoAlerteHandlerFactory(@Reference TimeZoneProvider timeZoneProvider) {
this.timeZoneProvider = timeZoneProvider;
this.gson = new GsonBuilder()
.registerTypeAdapter(ZonedDateTime.class, (JsonDeserializer<ZonedDateTime>) (json, type,
jsonDeserializationContext) -> ZonedDateTime.parse(json.getAsJsonPrimitive().getAsString()))
.create();
}

@Override
Expand All @@ -55,7 +65,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();

if (thingTypeUID.equals(THING_TYPE_METEO_ALERT)) {
return new MeteoAlerteHandler(thing, timeZoneProvider);
return new MeteoAlerteHandler(thing, timeZoneProvider, gson);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializer;

/**
* The {@link MeteoAlerteHandler} is responsible for updating channels
Expand All @@ -66,20 +64,17 @@ public class MeteoAlerteHandler extends BaseThingHandler {
private static final int TIMEOUT_MS = 30000;
private static final List<String> ALERT_LEVELS = Arrays.asList("Vert", "Jaune", "Orange", "Rouge");
private final Logger logger = LoggerFactory.getLogger(MeteoAlerteHandler.class);
private final Gson gson = new GsonBuilder()
.registerTypeAdapter(ZonedDateTime.class, (JsonDeserializer<ZonedDateTime>) (json, type,
jsonDeserializationContext) -> ZonedDateTime.parse(json.getAsJsonPrimitive().getAsString()))
.create();

// Time zone provider representing time zone configured in openHAB configuration
private final TimeZoneProvider timeZoneProvider;

private final Gson gson;
private @Nullable ScheduledFuture<?> refreshJob;
private String queryUrl = "";

public MeteoAlerteHandler(Thing thing, TimeZoneProvider timeZoneProvider) {
public MeteoAlerteHandler(Thing thing, TimeZoneProvider timeZoneProvider, Gson gson) {
super(thing);
this.timeZoneProvider = timeZoneProvider;
this.gson = gson;
}

@Override
Expand All @@ -92,25 +87,23 @@ public void initialize() {

updateStatus(ThingStatus.UNKNOWN);
queryUrl = URL + config.department;
refreshJob = scheduler.scheduleWithFixedDelay(this::updateAndPublish, 0, config.refresh, TimeUnit.HOURS);
refreshJob = scheduler.scheduleWithFixedDelay(this::updateAndPublish, 0, config.refresh, TimeUnit.MINUTES);
}

@Override
public void dispose() {
logger.debug("Disposing the Météo Alerte handler.");
ScheduledFuture<?> refreshJob = this.refreshJob;
if (refreshJob != null && !refreshJob.isCancelled()) {
if (refreshJob != null) {
refreshJob.cancel(true);
this.refreshJob = null;
}
this.refreshJob = null;
}

@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
updateAndPublish();
} else {
logger.debug("The Meteo Alerte binding is read-only and can not handle command {}", command);
}
}

Expand All @@ -124,8 +117,8 @@ private void updateAndPublish() {
ApiResponse apiResponse = gson.fromJson(response, ApiResponse.class);
updateChannels(apiResponse);
} catch (MalformedURLException e) {
logger.warn("Malformed URL in Météo Alerte request : {}", queryUrl);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
String.format("Querying '%s' raised : %s", queryUrl, e.getMessage()));
} catch (IOException e) {
logger.warn("Error opening connection to Meteo Alerte webservice : {}", e.getMessage());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
Expand All @@ -138,29 +131,28 @@ private void updateAndPublish() {
* @param channelId the id identifying the channel to be updated
*/
private void updateChannels(ApiResponse apiResponse) {
Arrays.stream(apiResponse.getRecords()).findFirst().ifPresent(record -> {
record.getFields().ifPresent(fields -> {
updateAlertString(WIND, fields.getVent());
updateAlertString(RAIN, fields.getPluieInondation());
updateAlertString(STORM, fields.getOrage());
updateAlertString(FLOOD, fields.getInondation());
updateAlertString(SNOW, fields.getNeige());
updateAlertString(HEAT, fields.getCanicule());
updateAlertString(FREEZE, fields.getGrandFroid());
updateAlertString(AVALANCHE, fields.getAvalanches());

fields.getDateInsert().ifPresent(date -> updateDate(OBSERVATION_TIME, date));
updateState(COMMENT, new StringType(fields.getVigilanceComment()));
updateIcon(WIND, fields.getVent());
updateIcon(RAIN, fields.getPluieInondation());
updateIcon(STORM, fields.getOrage());
updateIcon(FLOOD, fields.getInondation());
updateIcon(SNOW, fields.getNeige());
updateIcon(HEAT, fields.getCanicule());
updateIcon(FREEZE, fields.getGrandFroid());
updateIcon(AVALANCHE, fields.getAvalanches());
});
});
Arrays.stream(apiResponse.getRecords()).findFirst()
.ifPresent((record) -> record.getResponseFieldDTO().ifPresent(fields -> {
updateAlertString(WIND, fields.getVent());
updateAlertString(RAIN, fields.getPluieInondation());
updateAlertString(STORM, fields.getOrage());
updateAlertString(FLOOD, fields.getInondation());
updateAlertString(SNOW, fields.getNeige());
updateAlertString(HEAT, fields.getCanicule());
updateAlertString(FREEZE, fields.getGrandFroid());
updateAlertString(AVALANCHE, fields.getAvalanches());

fields.getDateInsert().ifPresent(date -> updateDate(OBSERVATION_TIME, date));
updateState(COMMENT, new StringType(fields.getVigilanceComment()));
updateIcon(WIND, fields.getVent());
updateIcon(RAIN, fields.getPluieInondation());
updateIcon(STORM, fields.getOrage());
updateIcon(FLOOD, fields.getInondation());
updateIcon(SNOW, fields.getNeige());
updateIcon(HEAT, fields.getCanicule());
updateIcon(FREEZE, fields.getGrandFroid());
updateIcon(AVALANCHE, fields.getAvalanches());
}));
}

public void updateIcon(String channelId, String value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public class Record {
private String recordId = "";
@SerializedName("record_timestamp")
private String recordTimestamp = "";
private @Nullable Fields fields;
@SerializedName("fields")
private @Nullable ResponseFieldDTO responseFieldDTO;

public String getDatasetId() {
return datasetId;
Expand All @@ -47,8 +48,8 @@ public String getRecordTimestamp() {
return recordTimestamp;
}

public Optional<Fields> getFields() {
Fields fields = this.fields;
public Optional<ResponseFieldDTO> getResponseFieldDTO() {
ResponseFieldDTO fields = this.responseFieldDTO;
if (fields != null) {
return Optional.of(fields);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
import com.google.gson.annotations.SerializedName;

/**
* The {@link Fields} is the Java class used to map the JSON
* 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 Fields {
public class ResponseFieldDTO {
@SerializedName("nom_reg")
private String nomReg = "";
@SerializedName("typeprev")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@
</options>
<limitToOptions>true</limitToOptions>
</parameter>
<parameter name="refresh" type="integer" min="1" required="true" unit="h">
<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 (heure).</description>
<default>24</default>
<description>Période d'actualisation des données en minutes.</description>
<default>1440</default>
</parameter>
</config-description>
</thing-type>
Expand Down