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

[meteofrance] Documentation enhancements and more #17740

Merged
merged 5 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions bundles/org.openhab.binding.meteofrance/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The `rain-forecast` thing has this configuration parameters:
|-----------|--------------------------------------------------------------|
| location | Geo coordinates to be considered by the service. |

## Channels
## Channels for `vigilance`

The information that are retrieved is available as these channels:

Expand Down Expand Up @@ -78,6 +78,24 @@ The information that are retrieved is available as these channels:
| 2 | Orange | Be "very vigilant" in the concerned areas |
| 3 | Red | Absolute vigilance required |

## Channels for `rain-forecast`

The information that are retrieved is available as these channels:

| Channel ID | Item Type | Description |
|--------------|-----------|--------------------------|
| update-time | DateTime | Observation Timestamp |
| intensity | Number | Rain intensity level (*) |

(*) Rain intensity values and associated descriptions:

| Code | Description |
|------|---------------|
| 0 | Dry Weather |
| 1 | Light Rain |
| 2 | Moderate Rain |
| 3 | Heavy Rain |

## Provided icon set

This binding has its own IconProvider and makes available the following list of icons
Expand All @@ -101,7 +119,10 @@ This binding has its own IconProvider and makes available the following list of
meteoalert.things:

```java
Thing meteofrance:department:yvelines @ "MyCity" [department="78", refresh=12]
Bridge meteofrance:api:local "Portail Météo-France" [ apikey="ey......FIjG1MIC9lmG5t6HygPAPg=="] {
vigilance yvelines "Vigilance Météo" [ department="78" ]
rain-forecast yvelines [ location="48.764207,2.05948" ]
}
```

meteoalert.items:
Expand Down Expand Up @@ -129,4 +150,17 @@ Image MA_icon_avalanche "Avalanche" <oh:meteofranc

DateTime MA_ObservationTS "Timestamp [%1$tH:%1$tM]" <time> (gMeteoAlert) {channel="meteofrance:department:yvelines:observation-time"}

Number Intensite_Pluie "Intensité Pluie" <oh:meteofrance:intensity> (gMeteoAlert) {channel="meteofrance:rain-forecast:yvelines:intensity" }
```

jdbc.persist:

```java

Items {
* : strategy = everyChange
Intensite_Pluie : strategy = forecast
}


```
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
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;
Expand All @@ -49,6 +48,11 @@ public class DepartmentDbService {

public record Department(String id, String name, double northestLat, double southestLat, double eastestLon,
double westestLon) {

boolean contains(double latitude, double longitude) {
return northestLat >= latitude && southestLat <= latitude && //
westestLon <= longitude && eastestLon >= longitude;
}
}

@Activate
Expand All @@ -58,7 +62,7 @@ public DepartmentDbService() {
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());
logger.debug("Successfully loaded {} French departments", departments.size());
} catch (IOException | JsonSyntaxException | JsonIOException e) {
logger.warn("Unable to load departments list: {}", e.getMessage());
}
Expand All @@ -67,11 +71,6 @@ public DepartmentDbService() {
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);
return departments.stream().filter(dep -> dep.contains(latitude, longitude)).toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public record Product(//
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();
List<TextBlocItem> local = textBlocItems;
return local != null ? local.stream().filter(ti -> ti.validFor(searched)).findFirst() : Optional.empty();
}

public Optional<Period> getPeriod(Term term) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static org.openhab.binding.meteofrance.internal.MeteoFranceBindingConstants.REQUEST_TIMEOUT_MS;

import java.io.IOException;
import java.util.Locale;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -159,10 +160,13 @@ public Optional<Meta> getMeta() {
}

public @Nullable RainForecast getRainForecast(PointType location) {
String url = RAIN_FORECAST_BASE_URL.formatted(location.getLatitude().doubleValue(),
String url = String.format(Locale.US, RAIN_FORECAST_BASE_URL, location.getLatitude().doubleValue(),
location.getLongitude().doubleValue());
try {
logger.debug("Sending rain-forecast request to: {}", url);
String answer = HttpUtil.executeUrl(HttpMethod.GET, url, REQUEST_TIMEOUT_MS);
logger.debug("Received answer: {}", answer);

return deserializer.deserialize(RainForecast.class, answer);
} catch (MeteoFranceException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ private void updateAndPublish() {
location.ifPresent(loc -> {
RainForecast forecast = handler.getRainForecast(loc);
if (forecast != null) {
updateStatus(ThingStatus.ONLINE);
setProperties(forecast.properties);
updateDate(UPDATE_TIME, forecast.updateTime);
updateStatus(ThingStatus.ONLINE);
}
});
}, () -> logger.warn("No viable bridge"));
Expand All @@ -142,19 +142,29 @@ private void setProperties(@Nullable Properties forecastProps) {

private void setForecast(List<Forecast> forecast) {
TimeSeries timeSeries = new TimeSeries(REPLACE);
ZonedDateTime now = ZonedDateTime.now();

forecast.forEach(prevision -> {
State currentState = null;
long untilNextRun = 0;
for (Forecast prevision : forecast) {
State state = prevision.rainIntensity() != RainIntensity.UNKNOWN
? new DecimalType(prevision.rainIntensity().ordinal())
: UnDefType.UNDEF;
if (currentState == null) {
currentState = state;
if (prevision.time().isAfter(now)) {
untilNextRun = now.until(prevision.time(), ChronoUnit.SECONDS);
}
}
timeSeries.add(prevision.time().toInstant(), state);
});
}
updateState(intensityChannelUID, currentState == null ? UnDefType.UNDEF : currentState);
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));
untilNextRun = untilNextRun != 0 ? untilNextRun : 300;

logger.debug("Refresh rain intensity forecast in: {}s", untilNextRun);
refreshJob = Optional.of(scheduler.schedule(this::updateAndPublish, untilNextRun, TimeUnit.SECONDS));
}

private void updateDate(String channelId, @Nullable ZonedDateTime zonedDateTime) {
Expand Down