mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[openweathermap] Added support for Air Pollution API (#10343)
Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
parent
1fa1f54272
commit
b1e48e0db9
@ -10,7 +10,7 @@ This binding integrates the [OpenWeatherMap weather API](https://openweathermap.
|
||||
|
||||
## Supported Things
|
||||
|
||||
There are five supported things.
|
||||
There are six supported things.
|
||||
|
||||
### OpenWeatherMap Account
|
||||
|
||||
@ -38,6 +38,13 @@ The third thing `uvindex` supports the [current UV Index](https://openweathermap
|
||||
It requires coordinates of the location of your interest.
|
||||
You can add as much `uvindex` things for different locations to your setup as you like to observe.
|
||||
|
||||
### Current And Forecasted Air Pollution
|
||||
|
||||
Another thing is the `air-pollution` which provides the [current air pollution](https://openweathermap.org/api/air-pollution) and [forecasted air pollution](https://openweathermap.org/api/air-pollution#forecast) for a specific location.
|
||||
It requires coordinates of the location of your interest.
|
||||
Air pollution forecast is available for 5 days with hourly granularity.
|
||||
You can add as much `air-pollution` things for different locations to your setup as you like to observe.
|
||||
|
||||
### One Call API Weather and Forecast
|
||||
|
||||
The thing `onecall` supports the [current and forecast weather data](https://openweathermap.org/api/one-call-api#how) for a specific location using the One Call API.
|
||||
@ -78,13 +85,22 @@ Once the parameters `forecastHours` or `forecastDays` will be changed, the avail
|
||||
|
||||
### Current UV Index And Forecast
|
||||
|
||||
| Parameter | Description |
|
||||
|----------------|--------------------------------------------------------------------------------------------------------------------------------|
|
||||
| location | Location of weather in geographical coordinates (latitude/longitude/altitude). **Mandatory** |
|
||||
| Parameter | Description |
|
||||
|----------------|----------------------------------------------------------------------------------------------------------------------------------|
|
||||
| location | Location of weather in geographical coordinates (latitude/longitude/altitude). **Mandatory** |
|
||||
| forecastDays | Number of days for UV Index forecast (including todays forecast). Optional, the default value is 6 (min="1", max="8", step="1"). |
|
||||
|
||||
Once the parameter `forecastDays` will be changed, the available channel groups on the thing will be created or removed accordingly.
|
||||
|
||||
### Current Air Pollution And Forecast
|
||||
|
||||
| Parameter | Description |
|
||||
|----------------|--------------------------------------------------------------------------------------------------------------------------------|
|
||||
| location | Location of weather in geographical coordinates (latitude/longitude/altitude). **Mandatory** |
|
||||
| forecastHours | Number of hours for air pollution forecast. Optional, the default value is 0 (min="0", max="120", step="1"). |
|
||||
|
||||
Once the parameter `forecastHours` will be changed, the available channel groups on the thing will be created or removed accordingly.
|
||||
|
||||
### One Call API Weather and Forecast
|
||||
|
||||
| Parameter | Description |
|
||||
@ -188,6 +204,8 @@ See above for a description of the available channels.
|
||||
| Channel Group ID | Channel ID | Item Type | Description |
|
||||
|------------------------------------------------------------------|----------------------|----------------------|-----------------------------------------------------------------------------------|
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | time-stamp | DateTime | Date of data forecasted. |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | sunrise | DateTime | Time of sunrise for the given day. |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | sunset | DateTime | Time of sunset for the given day. |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition | String | Forecast weather condition. |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | condition-id | String | Id of the forecasted weather condition. **Advanced** |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | icon | Image | Icon representing the forecasted weather condition. |
|
||||
@ -205,6 +223,7 @@ See above for a description of the available channels.
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay16 | snow | Number:Length | Expected snow volume of a day. |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | dew-point | Number:Temperature | Expected dew-point. Only available in the One Call API |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | uvindex | Number | Forecasted Midday UV Index. Only available in the One Call API |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | precip-probability | Number:Dimensionless | Precipitation probability. |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | morning-temperature | Number:Temperature | Expected morning temperature. Only available in the One Call API |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | day-temperature | Number:Temperature | Expected day-temperature. Only available in the One Call API |
|
||||
| forecastToday, forecastTomorrow, forecastDay2, ... forecastDay7 | evening-temperature | Number:Temperature | Expected evening-temperature. Only available in the One Call API |
|
||||
@ -223,6 +242,21 @@ See above for a description of the available channels.
|
||||
|
||||
The `uvindex` channel is also available in the current data and the daily forecast of the One Call API.
|
||||
|
||||
### Air Pollution
|
||||
|
||||
| Channel Group ID | Channel ID | Item Type | Description |
|
||||
|-----------------------------------------------------------------|------------------------|----------------|--------------------------------------------------------------------------|
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | time-stamp | DateTime | Date of data observation / forecast. |
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | airQualityIndex | Number | Current or forecasted air quality index. |
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | particulateMatter2dot5 | Number:Density | Current or forecasted density of particles less than 2.5 µm in diameter. |
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | particulateMatter10 | Number:Density | Current or forecasted density of particles less than 10 µm in diameter. |
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | carbonMonoxide | Number:Density | Current or forecasted concentration of carbon monoxide. |
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | nitrogenMonoxide | Number:Density | Current or forecasted concentration of nitrogen monoxide. |
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | nitrogenDioxide | Number:Density | Current or forecasted concentration of nitrogen dioxide. |
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | ozone | Number:Density | Current or forecasted concentration of ozone. |
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | sulphurDioxide | Number:Density | Current or forecasted concentration of sulphur dioxide. |
|
||||
| current, forecastHours01, forecastHours02, ... forecastHours120 | ammonia | Number:Density | Current or forecasted concentration of ammonia. |
|
||||
|
||||
## Full Example
|
||||
|
||||
### Things
|
||||
|
@ -36,6 +36,7 @@ public class OpenWeatherMapBindingConstants {
|
||||
public static final ThingTypeUID THING_TYPE_WEATHER_AND_FORECAST = new ThingTypeUID(BINDING_ID,
|
||||
"weather-and-forecast");
|
||||
public static final ThingTypeUID THING_TYPE_UVINDEX = new ThingTypeUID(BINDING_ID, "uvindex");
|
||||
public static final ThingTypeUID THING_TYPE_AIR_POLLUTION = new ThingTypeUID(BINDING_ID, "air-pollution");
|
||||
// One Call API forecast
|
||||
public static final ThingTypeUID THING_TYPE_ONECALL_WEATHER_AND_FORECAST = new ThingTypeUID(BINDING_ID, "onecall");
|
||||
// One Call API historical data
|
||||
@ -54,6 +55,8 @@ public class OpenWeatherMapBindingConstants {
|
||||
"dailyForecast");
|
||||
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_UVINDEX_FORECAST = new ChannelGroupTypeUID(BINDING_ID,
|
||||
"uvindexForecast");
|
||||
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_AIR_POLLUTION_FORECAST = new ChannelGroupTypeUID(
|
||||
BINDING_ID, "airPollutionForecast");
|
||||
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_ONECALL_MINUTELY_FORECAST = new ChannelGroupTypeUID(
|
||||
BINDING_ID, "oneCallMinutely");
|
||||
public static final ChannelGroupTypeUID CHANNEL_GROUP_TYPE_ONECALL_HOURLY_FORECAST = new ChannelGroupTypeUID(
|
||||
@ -69,6 +72,7 @@ public class OpenWeatherMapBindingConstants {
|
||||
public static final String CHANNEL_GROUP_FORECAST_TODAY = "forecastToday";
|
||||
public static final String CHANNEL_GROUP_FORECAST_TOMORROW = "forecastTomorrow";
|
||||
public static final String CHANNEL_GROUP_CURRENT_UVINDEX = "current";
|
||||
public static final String CHANNEL_GROUP_CURRENT_AIR_POLLUTION = "current";
|
||||
public static final String CHANNEL_GROUP_ONECALL_CURRENT = "current";
|
||||
public static final String CHANNEL_GROUP_ONECALL_HISTORY = "history";
|
||||
public static final String CHANNEL_GROUP_ONECALL_TODAY = "forecastToday";
|
||||
@ -109,6 +113,15 @@ public class OpenWeatherMapBindingConstants {
|
||||
public static final String CHANNEL_SNOW = "snow";
|
||||
public static final String CHANNEL_VISIBILITY = "visibility";
|
||||
public static final String CHANNEL_UVINDEX = "uvindex";
|
||||
public static final String CHANNEL_AIR_QUALITY_INDEX = "airQualityIndex";
|
||||
public static final String CHANNEL_PARTICULATE_MATTER_2_5 = "particulateMatter2dot5";
|
||||
public static final String CHANNEL_PARTICULATE_MATTER_10 = "particulateMatter10";
|
||||
public static final String CHANNEL_CARBON_MONOXIDE = "carbonMonoxide";
|
||||
public static final String CHANNEL_NITROGEN_MONOXIDE = "nitrogenMonoxide";
|
||||
public static final String CHANNEL_NITROGEN_DIOXIDE = "nitrogenDioxide";
|
||||
public static final String CHANNEL_OZONE = "ozone";
|
||||
public static final String CHANNEL_SULPHUR_DIOXIDE = "sulphurDioxide";
|
||||
public static final String CHANNEL_AMMONIA = "ammonia";
|
||||
public static final String CHANNEL_PRECIPITATION = "precipitation";
|
||||
|
||||
// List of all configuration
|
||||
|
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.openweathermap.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapAirPollutionHandler;
|
||||
|
||||
/**
|
||||
* The {@link OpenWeatherMapAirPollutionConfiguration} is the class used to match the
|
||||
* {@link OpenWeatherMapAirPollutionHandler}s configuration.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class OpenWeatherMapAirPollutionConfiguration extends OpenWeatherMapLocationConfiguration {
|
||||
public int forecastHours;
|
||||
}
|
@ -35,6 +35,7 @@ import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.HttpResponseException;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.openhab.binding.openweathermap.internal.config.OpenWeatherMapAPIConfiguration;
|
||||
import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonAirPollutionData;
|
||||
import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonDailyForecastData;
|
||||
import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonHourlyForecastData;
|
||||
import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonUVIndexData;
|
||||
@ -88,6 +89,9 @@ public class OpenWeatherMapConnection {
|
||||
// UV Index (see https://openweathermap.org/api/uvi)
|
||||
private static final String UVINDEX_URL = "https://api.openweathermap.org/data/2.5/uvi";
|
||||
private static final String UVINDEX_FORECAST_URL = "https://api.openweathermap.org/data/2.5/uvi/forecast";
|
||||
// Air Pollution (see https://openweathermap.org/api/air-pollution)
|
||||
private static final String AIR_POLLUTION_URL = "https://api.openweathermap.org/data/2.5/air_pollution";
|
||||
private static final String AIR_POLLUTION_FORECAST_URL = "https://api.openweathermap.org/data/2.5/air_pollution/forecast";
|
||||
// Weather icons (see https://openweathermap.org/weather-conditions)
|
||||
private static final String ICON_URL = "https://openweathermap.org/img/w/%s.png";
|
||||
// One Call API (see https://openweathermap.org/api/one-call-api )
|
||||
@ -176,7 +180,7 @@ public class OpenWeatherMapConnection {
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the UV Index data for the given location (see https://api.openweathermap.org/data/2.5/uvi).
|
||||
* Requests the UV Index data for the given location (see https://openweathermap.org/api/uvi).
|
||||
*
|
||||
* @param location location represented as {@link PointType}
|
||||
* @return the UV Index data
|
||||
@ -193,7 +197,7 @@ public class OpenWeatherMapConnection {
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the UV Index forecast data for the given location (see https://api.openweathermap.org/data/2.5/uvi).
|
||||
* Requests the UV Index forecast data for the given location (see https://openweathermap.org/api/uvi).
|
||||
*
|
||||
* @param location location represented as {@link PointType}
|
||||
* @return the UV Index forecast data
|
||||
@ -216,6 +220,42 @@ public class OpenWeatherMapConnection {
|
||||
OpenWeatherMapJsonUVIndexData[].class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the Air Pollution data for the given location (see https://openweathermap.org/api/air-pollution).
|
||||
*
|
||||
* @param location location represented as {@link PointType}
|
||||
* @return the Air Pollution data
|
||||
* @throws JsonSyntaxException
|
||||
* @throws OpenWeatherMapCommunicationException
|
||||
* @throws OpenWeatherMapConfigurationException
|
||||
*/
|
||||
public synchronized @Nullable OpenWeatherMapJsonAirPollutionData getAirPollutionData(@Nullable PointType location)
|
||||
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
|
||||
return gson.fromJson(
|
||||
getResponseFromCache(
|
||||
buildURL(AIR_POLLUTION_URL, getRequestParams(handler.getOpenWeatherMapAPIConfig(), location))),
|
||||
OpenWeatherMapJsonAirPollutionData.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the Air Pollution forecast data for the given location (see
|
||||
* https://openweathermap.org/api/air-pollution).
|
||||
*
|
||||
* @param location location represented as {@link PointType}
|
||||
* @return the Air Pollution forecast data
|
||||
* @throws JsonSyntaxException
|
||||
* @throws OpenWeatherMapCommunicationException
|
||||
* @throws OpenWeatherMapConfigurationException
|
||||
*/
|
||||
public synchronized @Nullable OpenWeatherMapJsonAirPollutionData getAirPollutionForecastData(
|
||||
@Nullable PointType location)
|
||||
throws JsonSyntaxException, OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
|
||||
return gson.fromJson(
|
||||
getResponseFromCache(buildURL(AIR_POLLUTION_FORECAST_URL,
|
||||
getRequestParams(handler.getOpenWeatherMapAPIConfig(), location))),
|
||||
OpenWeatherMapJsonAirPollutionData.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the icon for the given icon id (see https://openweathermap.org/weather-conditions).
|
||||
*
|
||||
@ -317,7 +357,7 @@ public class OpenWeatherMapConnection {
|
||||
}
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// API key (see http://openweathermap.org/appid)
|
||||
// API key (see https://openweathermap.org/appid)
|
||||
String apikey = config.apikey;
|
||||
if (apikey == null || (apikey = apikey.trim()).isEmpty()) {
|
||||
throw new OpenWeatherMapConfigurationException("@text/offline.conf-error-missing-apikey");
|
||||
|
@ -129,6 +129,7 @@ public class OpenWeatherMapDiscoveryService extends AbstractDiscoveryService {
|
||||
String locationString = location.toFullString();
|
||||
ThingUID bridgeUID = bridgeHandler.getThing().getUID();
|
||||
createWeatherAndForecastResult(locationString, bridgeUID);
|
||||
createAirPollutionResult(locationString, bridgeUID);
|
||||
createOneCallResult(locationString, bridgeUID);
|
||||
createOneCallHistoryResult(locationString, bridgeUID);
|
||||
}
|
||||
@ -139,6 +140,12 @@ public class OpenWeatherMapDiscoveryService extends AbstractDiscoveryService {
|
||||
.withRepresentationProperty(CONFIG_LOCATION).withBridge(bridgeUID).build());
|
||||
}
|
||||
|
||||
private void createAirPollutionResult(String location, ThingUID bridgeUID) {
|
||||
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_AIR_POLLUTION, bridgeUID, LOCAL))
|
||||
.withLabel("Local Air Pollution").withProperty(CONFIG_LOCATION, location)
|
||||
.withRepresentationProperty(CONFIG_LOCATION).withBridge(bridgeUID).build());
|
||||
}
|
||||
|
||||
private void createOneCallResult(String location, ThingUID bridgeUID) {
|
||||
thingDiscovered(
|
||||
DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_ONECALL_WEATHER_AND_FORECAST, bridgeUID, LOCAL))
|
||||
|
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.openweathermap.internal.dto;
|
||||
|
||||
import org.openhab.binding.openweathermap.internal.dto.base.Coord;
|
||||
|
||||
/**
|
||||
* The {@link OpenWeatherMapJsonAirPollutionData} is the Java class used to map the JSON response to an OpenWeatherMap
|
||||
* request.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
public class OpenWeatherMapJsonAirPollutionData {
|
||||
public Coord coord;
|
||||
public java.util.List<org.openhab.binding.openweathermap.internal.dto.airpollution.List> list;
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.openweathermap.internal.dto.airpollution;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link Components} from JSON.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
public class Components {
|
||||
@SerializedName("co")
|
||||
public double carbonMonoxide;
|
||||
@SerializedName("no")
|
||||
public double nitrogenMonoxide;
|
||||
@SerializedName("no2")
|
||||
public double nitrogenDioxide;
|
||||
@SerializedName("o2")
|
||||
public double ozone;
|
||||
@SerializedName("so2")
|
||||
public double sulphurDioxide;
|
||||
@SerializedName("pm2_5")
|
||||
public double particulateMatter2dot5;
|
||||
@SerializedName("pm10")
|
||||
public double particulateMatter10;
|
||||
@SerializedName("nh3")
|
||||
public double ammonia;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.openweathermap.internal.dto.airpollution;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link List} from JSON.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
public class List {
|
||||
public int dt;
|
||||
@SerializedName("main")
|
||||
public Main airQualityIndex;
|
||||
@SerializedName("components")
|
||||
public Components measurements;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.openweathermap.internal.dto.airpollution;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link Main} from JSON.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
public class Main {
|
||||
@SerializedName("aqi")
|
||||
public int index;
|
||||
}
|
@ -24,6 +24,8 @@ import com.google.gson.annotations.SerializedName;
|
||||
*/
|
||||
public class List {
|
||||
private Integer dt;
|
||||
private @Nullable Integer sunrise;
|
||||
private @Nullable Integer sunset;
|
||||
private Temp temp;
|
||||
@SerializedName("feels_like")
|
||||
private @Nullable FeelsLikeTemp feelsLikeTemp;
|
||||
@ -36,6 +38,7 @@ public class List {
|
||||
private Integer clouds;
|
||||
private @Nullable Double rain;
|
||||
private @Nullable Double snow;
|
||||
private @Nullable Double pop;
|
||||
|
||||
public Integer getDt() {
|
||||
return dt;
|
||||
@ -45,6 +48,22 @@ public class List {
|
||||
this.dt = dt;
|
||||
}
|
||||
|
||||
public @Nullable Integer getSunrise() {
|
||||
return sunrise;
|
||||
}
|
||||
|
||||
public void setSunrise(Integer sunrise) {
|
||||
this.sunrise = sunrise;
|
||||
}
|
||||
|
||||
public @Nullable Integer getSunset() {
|
||||
return sunset;
|
||||
}
|
||||
|
||||
public void setSunset(Integer sunset) {
|
||||
this.sunset = sunset;
|
||||
}
|
||||
|
||||
public Temp getTemp() {
|
||||
return temp;
|
||||
}
|
||||
@ -132,4 +151,12 @@ public class List {
|
||||
public void setSnow(Double snow) {
|
||||
this.snow = snow;
|
||||
}
|
||||
|
||||
public @Nullable Double getPop() {
|
||||
return pop;
|
||||
}
|
||||
|
||||
public void setPop(Double pop) {
|
||||
this.pop = pop;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import static org.openhab.binding.openweathermap.internal.OpenWeatherMapBindingC
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@ -26,7 +25,13 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.openweathermap.internal.discovery.OpenWeatherMapDiscoveryService;
|
||||
import org.openhab.binding.openweathermap.internal.handler.*;
|
||||
import org.openhab.binding.openweathermap.internal.handler.AbstractOpenWeatherMapHandler;
|
||||
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapAPIHandler;
|
||||
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapAirPollutionHandler;
|
||||
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapOneCallHandler;
|
||||
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapOneCallHistoryHandler;
|
||||
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapUVIndexHandler;
|
||||
import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapWeatherAndForecastHandler;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.LocationProvider;
|
||||
@ -90,13 +95,15 @@ public class OpenWeatherMapHandlerFactory extends BaseThingHandlerFactory {
|
||||
// register discovery service
|
||||
OpenWeatherMapDiscoveryService discoveryService = new OpenWeatherMapDiscoveryService(handler,
|
||||
locationProvider, localeProvider, i18nProvider);
|
||||
discoveryServiceRegs.put(handler.getThing().getUID(), bundleContext
|
||||
.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
|
||||
discoveryServiceRegs.put(handler.getThing().getUID(),
|
||||
bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, null));
|
||||
return handler;
|
||||
} else if (THING_TYPE_WEATHER_AND_FORECAST.equals(thingTypeUID)) {
|
||||
return new OpenWeatherMapWeatherAndForecastHandler(thing, timeZoneProvider);
|
||||
} else if (THING_TYPE_UVINDEX.equals(thingTypeUID)) {
|
||||
return new OpenWeatherMapUVIndexHandler(thing, timeZoneProvider);
|
||||
} else if (THING_TYPE_AIR_POLLUTION.equals(thingTypeUID)) {
|
||||
return new OpenWeatherMapAirPollutionHandler(thing, timeZoneProvider);
|
||||
} else if (THING_TYPE_ONECALL_WEATHER_AND_FORECAST.equals(thingTypeUID)) {
|
||||
return new OpenWeatherMapOneCallHandler(thing, timeZoneProvider);
|
||||
} else if (THING_TYPE_ONECALL_HISTORY.equals(thingTypeUID)) {
|
||||
|
@ -17,11 +17,8 @@ import static org.openhab.binding.openweathermap.internal.OpenWeatherMapBindingC
|
||||
import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
@ -69,9 +66,9 @@ public abstract class AbstractOpenWeatherMapHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(AbstractOpenWeatherMapHandler.class);
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections
|
||||
.unmodifiableSet(Stream.of(THING_TYPE_WEATHER_AND_FORECAST, THING_TYPE_UVINDEX,
|
||||
THING_TYPE_ONECALL_WEATHER_AND_FORECAST, THING_TYPE_ONECALL_HISTORY).collect(Collectors.toSet()));
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_WEATHER_AND_FORECAST,
|
||||
THING_TYPE_UVINDEX, THING_TYPE_AIR_POLLUTION, THING_TYPE_ONECALL_WEATHER_AND_FORECAST,
|
||||
THING_TYPE_ONECALL_HISTORY);
|
||||
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
|
||||
|
@ -14,7 +14,6 @@ package org.openhab.binding.openweathermap.internal.handler;
|
||||
|
||||
import static org.openhab.binding.openweathermap.internal.OpenWeatherMapBindingConstants.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -34,6 +33,7 @@ import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.util.ThingHandlerHelper;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
@ -49,7 +49,7 @@ public class OpenWeatherMapAPIHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(OpenWeatherMapAPIHandler.class);
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_WEATHER_API);
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_WEATHER_API);
|
||||
|
||||
private static final long INITIAL_DELAY_IN_SECONDS = 15;
|
||||
|
||||
@ -74,7 +74,7 @@ public class OpenWeatherMapAPIHandler extends BaseBridgeHandler {
|
||||
config = getConfigAs(OpenWeatherMapAPIConfiguration.class);
|
||||
|
||||
boolean configValid = true;
|
||||
if (config.apikey == null || config.apikey.trim().isEmpty()) {
|
||||
if (config.apikey.isBlank()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/offline.conf-error-missing-apikey");
|
||||
configValid = false;
|
||||
@ -172,7 +172,7 @@ public class OpenWeatherMapAPIHandler extends BaseBridgeHandler {
|
||||
}
|
||||
|
||||
private ThingStatus updateThing(@Nullable AbstractOpenWeatherMapHandler handler, Thing thing) {
|
||||
if (handler != null && connection != null) {
|
||||
if (handler != null && ThingHandlerHelper.isHandlerInitialized(handler) && connection != null) {
|
||||
handler.updateData(connection);
|
||||
return thing.getStatus();
|
||||
} else {
|
||||
|
@ -0,0 +1,262 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.openweathermap.internal.handler;
|
||||
|
||||
import static org.openhab.binding.openweathermap.internal.OpenWeatherMapBindingConstants.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.openweathermap.internal.config.OpenWeatherMapAirPollutionConfiguration;
|
||||
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapCommunicationException;
|
||||
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConfigurationException;
|
||||
import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConnection;
|
||||
import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonAirPollutionData;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link OpenWeatherMapAirPollutionHandler} is responsible for handling commands, which are sent to one of the
|
||||
* channels.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class OpenWeatherMapAirPollutionHandler extends AbstractOpenWeatherMapHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(OpenWeatherMapAirPollutionHandler.class);
|
||||
|
||||
private static final String CHANNEL_GROUP_HOURLY_FORECAST_PREFIX = "forecastHours";
|
||||
private static final Pattern CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN = Pattern
|
||||
.compile(CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + "([0-9]*)");
|
||||
|
||||
// keeps track of the parsed count
|
||||
private int forecastHours = 0;
|
||||
|
||||
private @Nullable OpenWeatherMapJsonAirPollutionData airPollutionData;
|
||||
private @Nullable OpenWeatherMapJsonAirPollutionData airPollutionForecastData;
|
||||
|
||||
public OpenWeatherMapAirPollutionHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
|
||||
super(thing, timeZoneProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
logger.debug("Initialize OpenWeatherMapAirPollutionHandler handler '{}'.", getThing().getUID());
|
||||
OpenWeatherMapAirPollutionConfiguration config = getConfigAs(OpenWeatherMapAirPollutionConfiguration.class);
|
||||
|
||||
boolean configValid = true;
|
||||
int newForecastHours = config.forecastHours;
|
||||
if (newForecastHours < 0 || newForecastHours > 120) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/offline.conf-error-not-supported-air-pollution-number-of-hours");
|
||||
configValid = false;
|
||||
}
|
||||
|
||||
if (configValid) {
|
||||
logger.debug("Rebuilding thing '{}'.", getThing().getUID());
|
||||
List<Channel> toBeAddedChannels = new ArrayList<>();
|
||||
List<Channel> toBeRemovedChannels = new ArrayList<>();
|
||||
if (forecastHours != newForecastHours) {
|
||||
logger.debug("Rebuilding air pollution channel groups.");
|
||||
if (forecastHours > newForecastHours) {
|
||||
for (int i = newForecastHours + 1; i <= forecastHours; i++) {
|
||||
toBeRemovedChannels.addAll(removeChannelsOfGroup(
|
||||
CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i)));
|
||||
}
|
||||
} else {
|
||||
for (int i = forecastHours + 1; i <= newForecastHours; i++) {
|
||||
toBeAddedChannels.addAll(createChannelsForGroup(
|
||||
CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i),
|
||||
CHANNEL_GROUP_TYPE_AIR_POLLUTION_FORECAST));
|
||||
}
|
||||
}
|
||||
forecastHours = newForecastHours;
|
||||
}
|
||||
ThingBuilder builder = editThing().withoutChannels(toBeRemovedChannels);
|
||||
for (Channel channel : toBeAddedChannels) {
|
||||
builder.withChannel(channel);
|
||||
}
|
||||
updateThing(builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requestData(OpenWeatherMapConnection connection)
|
||||
throws OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
|
||||
logger.debug("Update air pollution data of thing '{}'.", getThing().getUID());
|
||||
try {
|
||||
airPollutionData = connection.getAirPollutionData(location);
|
||||
if (forecastHours > 0) {
|
||||
airPollutionForecastData = connection.getAirPollutionForecastData(location);
|
||||
}
|
||||
return true;
|
||||
} catch (JsonSyntaxException e) {
|
||||
logger.debug("JsonSyntaxException occurred during execution: {}", e.getLocalizedMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateChannel(ChannelUID channelUID) {
|
||||
switch (channelUID.getGroupId()) {
|
||||
case CHANNEL_GROUP_CURRENT_AIR_POLLUTION:
|
||||
updateCurrentAirPollutionChannel(channelUID);
|
||||
break;
|
||||
default:
|
||||
Matcher m = CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN.matcher(channelUID.getGroupId());
|
||||
int i;
|
||||
if (m.find() && (i = Integer.parseInt(m.group(1))) > 0 && i <= 120) {
|
||||
updateHourlyForecastChannel(channelUID, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the channel from the last OpenWeatherMap data retrieved.
|
||||
*
|
||||
* @param channelUID the id identifying the channel to be updated
|
||||
*/
|
||||
private void updateCurrentAirPollutionChannel(ChannelUID channelUID) {
|
||||
String channelId = channelUID.getIdWithoutGroup();
|
||||
String channelGroupId = channelUID.getGroupId();
|
||||
OpenWeatherMapJsonAirPollutionData localAirPollutionData = airPollutionData;
|
||||
if (localAirPollutionData != null && !localAirPollutionData.list.isEmpty()) {
|
||||
org.openhab.binding.openweathermap.internal.dto.airpollution.List currentData = localAirPollutionData.list
|
||||
.get(0);
|
||||
State state = UnDefType.UNDEF;
|
||||
switch (channelId) {
|
||||
case CHANNEL_TIME_STAMP:
|
||||
state = getDateTimeTypeState(currentData.dt);
|
||||
break;
|
||||
case CHANNEL_AIR_QUALITY_INDEX:
|
||||
state = new DecimalType(currentData.airQualityIndex.index);
|
||||
break;
|
||||
case CHANNEL_PARTICULATE_MATTER_2_5:
|
||||
state = getQuantityTypeState(currentData.measurements.particulateMatter2dot5,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_PARTICULATE_MATTER_10:
|
||||
state = getQuantityTypeState(currentData.measurements.particulateMatter10,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_CARBON_MONOXIDE:
|
||||
state = getQuantityTypeState(currentData.measurements.carbonMonoxide,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_NITROGEN_MONOXIDE:
|
||||
state = getQuantityTypeState(currentData.measurements.nitrogenMonoxide,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_NITROGEN_DIOXIDE:
|
||||
state = getQuantityTypeState(currentData.measurements.nitrogenDioxide,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_OZONE:
|
||||
state = getQuantityTypeState(currentData.measurements.ozone, Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_SULPHUR_DIOXIDE:
|
||||
state = getQuantityTypeState(currentData.measurements.sulphurDioxide,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_AMMONIA:
|
||||
state = getQuantityTypeState(currentData.measurements.ammonia, Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
}
|
||||
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
|
||||
updateState(channelUID, state);
|
||||
} else {
|
||||
logger.debug("No air pollution data available to update channel '{}' of group '{}'.", channelId,
|
||||
channelGroupId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the channel from the last OpenWeatherMap data retrieved.
|
||||
*
|
||||
* @param channelUID the id identifying the channel to be updated
|
||||
* @param count
|
||||
*/
|
||||
private void updateHourlyForecastChannel(ChannelUID channelUID, int count) {
|
||||
String channelId = channelUID.getIdWithoutGroup();
|
||||
String channelGroupId = channelUID.getGroupId();
|
||||
OpenWeatherMapJsonAirPollutionData localAirPollutionForecastData = airPollutionForecastData;
|
||||
if (localAirPollutionForecastData != null && localAirPollutionForecastData.list.size() >= count) {
|
||||
org.openhab.binding.openweathermap.internal.dto.airpollution.List forecastData = localAirPollutionForecastData.list
|
||||
.get(count - 1);
|
||||
State state = UnDefType.UNDEF;
|
||||
switch (channelId) {
|
||||
case CHANNEL_TIME_STAMP:
|
||||
state = getDateTimeTypeState(forecastData.dt);
|
||||
break;
|
||||
case CHANNEL_AIR_QUALITY_INDEX:
|
||||
state = new DecimalType(forecastData.airQualityIndex.index);
|
||||
break;
|
||||
case CHANNEL_PARTICULATE_MATTER_2_5:
|
||||
state = getQuantityTypeState(forecastData.measurements.particulateMatter2dot5,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_PARTICULATE_MATTER_10:
|
||||
state = getQuantityTypeState(forecastData.measurements.particulateMatter10,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_CARBON_MONOXIDE:
|
||||
state = getQuantityTypeState(forecastData.measurements.carbonMonoxide,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_NITROGEN_MONOXIDE:
|
||||
state = getQuantityTypeState(forecastData.measurements.nitrogenMonoxide,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_NITROGEN_DIOXIDE:
|
||||
state = getQuantityTypeState(forecastData.measurements.nitrogenDioxide,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_OZONE:
|
||||
state = getQuantityTypeState(forecastData.measurements.ozone, Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_SULPHUR_DIOXIDE:
|
||||
state = getQuantityTypeState(forecastData.measurements.sulphurDioxide,
|
||||
Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
case CHANNEL_AMMONIA:
|
||||
state = getQuantityTypeState(forecastData.measurements.ammonia, Units.MICROGRAM_PER_CUBICMETRE);
|
||||
break;
|
||||
}
|
||||
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
|
||||
updateState(channelUID, state);
|
||||
} else {
|
||||
logger.debug("No air pollution data available to update channel '{}' of group '{}'.", channelId,
|
||||
channelGroupId);
|
||||
}
|
||||
}
|
||||
}
|
@ -428,6 +428,12 @@ public class OpenWeatherMapWeatherAndForecastHandler extends AbstractOpenWeather
|
||||
case CHANNEL_TIME_STAMP:
|
||||
state = getDateTimeTypeState(forecastData.getDt());
|
||||
break;
|
||||
case CHANNEL_SUNRISE:
|
||||
state = getDateTimeTypeState(forecastData.getSunrise());
|
||||
break;
|
||||
case CHANNEL_SUNSET:
|
||||
state = getDateTimeTypeState(forecastData.getSunset());
|
||||
break;
|
||||
case CHANNEL_CONDITION:
|
||||
if (!forecastData.getWeather().isEmpty()) {
|
||||
state = getStringTypeState(forecastData.getWeather().get(0).getDescription());
|
||||
@ -487,6 +493,10 @@ public class OpenWeatherMapWeatherAndForecastHandler extends AbstractOpenWeather
|
||||
Double snow = forecastData.getSnow();
|
||||
state = getQuantityTypeState(snow == null ? 0 : snow, MILLI(METRE));
|
||||
break;
|
||||
case CHANNEL_PRECIP_PROBABILITY:
|
||||
Double probability = forecastData.getPop();
|
||||
state = getQuantityTypeState(probability == null ? 0 : probability * 100.0, PERCENT);
|
||||
break;
|
||||
}
|
||||
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
|
||||
updateState(channelUID, state);
|
||||
|
@ -101,6 +101,19 @@
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:openweathermap:air-pollution">
|
||||
<parameter name="location" type="text" required="true">
|
||||
<context>location</context>
|
||||
<label>Location of Weather</label>
|
||||
<description>Location of weather in geographical coordinates (latitude/longitude/altitude).</description>
|
||||
</parameter>
|
||||
<parameter name="forecastHours" type="integer" min="0" max="120" step="1">
|
||||
<label>Number of Hours</label>
|
||||
<description>Number of hours for air pollution forecast.</description>
|
||||
<default>0</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:openweathermap:onecall">
|
||||
<parameter name="location" type="text" required="true">
|
||||
<context>location</context>
|
||||
|
@ -69,6 +69,9 @@ thing-type.openweathermap.weather-and-forecast.description = Erm
|
||||
thing-type.openweathermap.uvindex.label = UV-Index
|
||||
thing-type.openweathermap.uvindex.description = Ermöglicht die Anzeige des aktuellen UV-Index.
|
||||
|
||||
thing-type.openweathermap.air-pollution.label = Luftqualität
|
||||
thing-type.openweathermap.air-pollution.description = Ermöglicht die Anzeige der aktuellen Luftqualität.
|
||||
|
||||
# thing types config
|
||||
thing-type.config.openweathermap.weather-and-forecast.location.label = Ort der Wetterdaten
|
||||
thing-type.config.openweathermap.weather-and-forecast.location.description = Ort der Wetterdaten in geographischen Koordinaten (Breitengrad/Längengrad/Höhe).
|
||||
@ -85,6 +88,12 @@ thing-type.config.openweathermap.uvindex.location.description = Ort der Wetterda
|
||||
thing-type.config.openweathermap.uvindex.forecastDays.label = Tage
|
||||
thing-type.config.openweathermap.uvindex.forecastDays.description = Anzahl der Tage für die UV-Index Vorhersage.
|
||||
|
||||
thing-type.config.openweathermap.air-pollution.location.label = Ort der Wetterdaten
|
||||
thing-type.config.openweathermap.air-pollution.location.description = Ort der Wetterdaten in geographischen Koordinaten (Breitengrad/Längengrad/Höhe).
|
||||
|
||||
thing-type.config.openweathermap.air-pollution.forecastHours.label = Stunden
|
||||
thing-type.config.openweathermap.air-pollution.forecastHours.description = Anzahl der Stunden für die Vorhersage der Luftqualität.
|
||||
|
||||
# channel group types
|
||||
channel-group-type.openweathermap.station.label = Wetterstation
|
||||
channel-group-type.openweathermap.station.description = Fasst Daten über die Wetterstation oder den Ort zusammen.
|
||||
@ -104,6 +113,12 @@ channel-group-type.openweathermap.uvindex.description = Fasst aktuelle UV-Index
|
||||
channel-group-type.openweathermap.uvindexForecast.label = UV-Index Vorhersage
|
||||
channel-group-type.openweathermap.uvindexForecast.description = Fasst Daten der UV-Index Vorhersage zusammen.
|
||||
|
||||
channel-group-type.openweathermap.airPollution.label = Aktuelle Luftqualität
|
||||
channel-group-type.openweathermap.airPollution.description = Fasst Daten über die aktuelle Luftqualität zusammen.
|
||||
|
||||
channel-group-type.openweathermap.airPollutionForecast.label = Vorhersage der Luftqualität
|
||||
channel-group-type.openweathermap.airPollutionForecast.description = Fasst Daten über die vorhergesagte Luftqualität zusammen.
|
||||
|
||||
# channel groups
|
||||
thing-type.openweathermap.weather-and-forecast.group.forecastHours03.label = Wettervorhersage für 3 Stunden
|
||||
thing-type.openweathermap.weather-and-forecast.group.forecastHours03.description = Fasst Daten der Wettervorhersage in den nächsten drei Stunden zusammen.
|
||||
@ -184,6 +199,14 @@ channel-type.openweathermap.daily-forecast-time-stamp.label = Vorhersage Datum
|
||||
channel-type.openweathermap.daily-forecast-time-stamp.description = Zeigt das Datum der Vorhersage an.
|
||||
channel-type.openweathermap.daily-forecast-time-stamp.state.pattern = %1$td.%1$tm.%1$tY
|
||||
|
||||
channel-type.openweathermap.sunrise.label = Sonnenaufgang
|
||||
channel-type.openweathermap.sunrise.description = Zeigt den Zeitpunkt des Sonnenaufgangs an.
|
||||
channel-type.openweathermap.sunrise.state.pattern = %1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS
|
||||
|
||||
channel-type.openweathermap.sunset.label = Sonnenuntergang
|
||||
channel-type.openweathermap.sunset.description = Zeigt den Zeitpunkt des Sonnenuntergangs an.
|
||||
channel-type.openweathermap.sunset.state.pattern = %1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS
|
||||
|
||||
channel-type.openweathermap.condition.label = Wetterlage
|
||||
channel-type.openweathermap.condition.description = Zeigt die aktuelle Wetterlage an.
|
||||
|
||||
@ -253,12 +276,79 @@ channel-type.openweathermap.snow.description = Zeigt den kumulierten Schnee der
|
||||
channel-type.openweathermap.forecasted-snow.label = Vorhergesagter Schnee
|
||||
channel-type.openweathermap.forecasted-snow.description = Zeigt die vorhergesagte Schneemenge an.
|
||||
|
||||
channel-type.openweathermap.precip-probability.label = Vorhergesagte Niederschlagswahrscheinlichkeit
|
||||
channel-type.openweathermap.precip-probability.description = Zeigt die vorhergesagte Niederschlagswahrscheinlichkeit an.
|
||||
|
||||
channel-type.openweathermap.uvindex.label = UV-Index
|
||||
channel-type.openweathermap.uvindex.description = Zeigt den aktuellen UV-Index an.
|
||||
|
||||
channel-type.openweathermap.forecasted-uvindex.label = Vorhergesagter UV-Index
|
||||
channel-type.openweathermap.forecasted-uvindex.description = Zeigt den vorhergesagten UV-Index an.
|
||||
|
||||
channel-type.openweathermap.air-quality-index.label = Luftqualitätsindex
|
||||
channel-type.openweathermap.air-quality-index.description = Zeigt den aktuellen Luftqualitätsindex an.
|
||||
channel-type.openweathermap.air-quality-index.state.option.1 = Gut
|
||||
channel-type.openweathermap.air-quality-index.state.option.2 = Befriedigend
|
||||
channel-type.openweathermap.air-quality-index.state.option.3 = Moderat
|
||||
channel-type.openweathermap.air-quality-index.state.option.4 = Ungesund
|
||||
channel-type.openweathermap.air-quality-index.state.option.5 = Äußerst Ungesund
|
||||
|
||||
channel-type.openweathermap.forecasted-air-quality-index.label = Vorhergesagter Luftqualitätsindex
|
||||
channel-type.openweathermap.forecasted-air-quality-index.description = Zeigt den vorhergesagten Luftqualitätsindex an.
|
||||
channel-type.openweathermap.forecasted-air-quality-index.state.option.1 = Gut
|
||||
channel-type.openweathermap.forecasted-air-quality-index.state.option.2 = Befriedigend
|
||||
channel-type.openweathermap.forecasted-air-quality-index.state.option.3 = Moderat
|
||||
channel-type.openweathermap.forecasted-air-quality-index.state.option.4 = Ungesund
|
||||
channel-type.openweathermap.forecasted-air-quality-index.state.option.5 = Äußerst Ungesund
|
||||
|
||||
channel-type.openweathermap.particulate-matter-2dot5.label = Feinstaub - PM2.5
|
||||
channel-type.openweathermap.particulate-matter-2dot5.description = Aktuelle Dichte von Teilchen mit Partikelgröße unter 2,5 µm.
|
||||
|
||||
channel-type.openweathermap.forecasted-particulate-matter-2dot5.label = Vorhergesagter Feinstaub - PM2.5
|
||||
channel-type.openweathermap.forecasted-particulate-matter-2dot5.description = Vorhergesagte Dichte von Teilchen mit Partikelgröße unter 2,5 µm.
|
||||
|
||||
channel-type.openweathermap.particulate-matter-10.label = Feinstaub - PM10
|
||||
channel-type.openweathermap.particulate-matter-10.description = Aktuelle Dichte von Teilchen mit Partikelgröße unter 10 µm.
|
||||
|
||||
channel-type.openweathermap.forecasted-particulate-matter-10.label = Vorhergesagter Feinstaub - PM10
|
||||
channel-type.openweathermap.forecasted-particulate-matter-10.description = Vorhergesagte Dichte von Teilchen mit Partikelgröße unter 10 µm.
|
||||
|
||||
channel-type.openweathermap.carbon-monoxide.label = Kohlenmonoxid
|
||||
channel-type.openweathermap.carbon-monoxide.description = Aktuelle Konzentration an Kohlenmonoxid.
|
||||
|
||||
channel-type.openweathermap.forecasted-carbon-monoxide.label = Vorhergesagter Kohlenmonoxid
|
||||
channel-type.openweathermap.forecasted-carbon-monoxide.description = Vorhergesagte Konzentration an Kohlenmonoxid.
|
||||
|
||||
channel-type.openweathermap.nitrogen-monoxide.label = Stickstoffmonoxid
|
||||
channel-type.openweathermap.nitrogen-monoxide.description = Aktuelle Konzentration an Stickstoffmonoxid.
|
||||
|
||||
channel-type.openweathermap.forecasted-nitrogen-monoxide.label = Vorhergesagter Stickstoffmonoxid
|
||||
channel-type.openweathermap.forecasted-nitrogen-monoxide.description = Vorhergesagte Konzentration an Stickstoffmonoxid.
|
||||
|
||||
channel-type.openweathermap.nitrogen-dioxide.label = Stickstoffdioxid
|
||||
channel-type.openweathermap.nitrogen-dioxide.description = Aktuelle Konzentration an Stickstoffdioxid.
|
||||
|
||||
channel-type.openweathermap.forecasted-nitrogen-dioxide.label = Vorhergesagter Stickstoffdioxid
|
||||
channel-type.openweathermap.forecasted-nitrogen-dioxide.description = Vorhergesagte Konzentration an Stickstoffdioxid.
|
||||
|
||||
channel-type.openweathermap.ozone.label = Ozon
|
||||
channel-type.openweathermap.ozone.description = Aktuelle Konzentration an Ozon.
|
||||
|
||||
channel-type.openweathermap.forecasted-ozone.label = Vorhergesagter Ozon
|
||||
channel-type.openweathermap.forecasted-ozone.description = Vorhergesagte Konzentration an Ozon.
|
||||
|
||||
channel-type.openweathermap.sulphur-dioxide.label = Schwefeldioxid
|
||||
channel-type.openweathermap.sulphur-dioxide.description = Aktuelle Konzentration an Schwefeldioxid.
|
||||
|
||||
channel-type.openweathermap.forecasted-sulphur-dioxide.label = Vorhergesagter Schwefeldioxid
|
||||
channel-type.openweathermap.forecasted-sulphur-dioxide.description = Vorhergesagte Konzentration an Schwefeldioxid.
|
||||
|
||||
channel-type.openweathermap.ammonia.label = Ammoniak
|
||||
channel-type.openweathermap.ammonia.description = Aktuelle Konzentration an Ammoniak.
|
||||
|
||||
channel-type.openweathermap.forecasted-ammonia.label = Vorhergesagter Ammoniak
|
||||
channel-type.openweathermap.forecasted-ammonia.description = Vorhergesagte Konzentration an Ammoniak.
|
||||
|
||||
# thing status
|
||||
offline.conf-error-missing-apikey = Der Parameter 'API Schlüssel' muss konfiguriert werden.
|
||||
offline.conf-error-invalid-apikey = Ungültiger 'API Schlüssel'. Mehr Infos unter https://openweathermap.org/faq#error401.
|
||||
@ -270,6 +360,7 @@ offline.conf-error-parsing-location = Der Parameter 'Ort' kann nicht in Latitude
|
||||
offline.conf-error-not-supported-number-of-hours = Der Parameter 'forecastHours' muss zwischen 0 und 120 liegen - Schrittweite: 3.
|
||||
offline.conf-error-not-supported-number-of-days = Der Parameter 'forecastDays' muss zwischen 0 und 16 liegen.
|
||||
offline.conf-error-not-supported-uvindex-number-of-days = Der Parameter 'forecastDays' muss zwischen 1 und 8 liegen.
|
||||
offline.conf-error-not-supported-air-pollution-number-of-hours = Der Parameter 'forecastHours' muss zwischen 0 und 120 liegen - Schrittweite: 1.
|
||||
|
||||
offline.conf-error-not-supported-onecall-number-of-minutes = Der Parameter 'forecastMinutes' muss zwischen 0 and 60 liegen.
|
||||
offline.conf-error-not-supported-onecall-number-of-hours = Der Parameter 'forecastHours' muss zwischen 0 und 48 liegen.
|
||||
@ -278,3 +369,4 @@ offline.conf-error-not-supported-onecall-number-of-days = Der Parameter 'forecas
|
||||
# discovery result
|
||||
discovery.openweathermap.weather-and-forecast.api.local.label = Lokales Wetter und Wettervorhersage
|
||||
discovery.openweathermap.uvindex.api.local.label = Lokaler UV-Index
|
||||
discovery.openweathermap.air-pollution.api.local.label = Lokale Luftqualität
|
||||
|
@ -84,6 +84,9 @@
|
||||
<channel id="cloudiness" typeId="forecasted-cloudiness"/>
|
||||
<channel id="rain" typeId="forecasted-rain"/>
|
||||
<channel id="snow" typeId="forecasted-snow"/>
|
||||
<channel id="precip-probability" typeId="precip-probability"/>
|
||||
<channel id="sunrise" typeId="sunrise"/>
|
||||
<channel id="sunset" typeId="sunset"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
@ -105,6 +108,40 @@
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="airPollution">
|
||||
<label>Current Air Pollution</label>
|
||||
<description>This is the current air pollution.</description>
|
||||
<channels>
|
||||
<channel id="time-stamp" typeId="time-stamp"/>
|
||||
<channel id="airQualityIndex" typeId="air-quality-index"/>
|
||||
<channel id="particulateMatter2dot5" typeId="particulate-matter-2dot5"/>
|
||||
<channel id="particulateMatter10" typeId="particulate-matter-10"/>
|
||||
<channel id="carbonMonoxide" typeId="carbon-monoxide"/>
|
||||
<channel id="nitrogenMonoxide" typeId="nitrogen-monoxide"/>
|
||||
<channel id="nitrogenDioxide" typeId="nitrogen-dioxide"/>
|
||||
<channel id="ozone" typeId="ozone"/>
|
||||
<channel id="sulphurDioxide" typeId="sulphur-dioxide"/>
|
||||
<channel id="ammonia" typeId="ammonia"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="airPollutionForecast">
|
||||
<label>Forecasted Air Pollution</label>
|
||||
<description>This is the forecasted air pollution.</description>
|
||||
<channels>
|
||||
<channel id="time-stamp" typeId="hourly-forecast-time-stamp"/>
|
||||
<channel id="airQualityIndex" typeId="forecasted-air-quality-index"/>
|
||||
<channel id="particulateMatter2dot5" typeId="forecasted-particulate-matter-2dot5"/>
|
||||
<channel id="particulateMatter10" typeId="forecasted-particulate-matter-10"/>
|
||||
<channel id="carbonMonoxide" typeId="forecasted-carbon-monoxide"/>
|
||||
<channel id="nitrogenMonoxide" typeId="forecasted-nitrogen-monoxide"/>
|
||||
<channel id="nitrogenDioxide" typeId="forecasted-nitrogen-dioxide"/>
|
||||
<channel id="ozone" typeId="forecasted-ozone"/>
|
||||
<channel id="sulphurDioxide" typeId="forecasted-sulphur-dioxide"/>
|
||||
<channel id="ammonia" typeId="forecasted-ammonia"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="oneCallCurrent">
|
||||
<label>One Call API Current Weather</label>
|
||||
<description>Current weather data from the One Call API.</description>
|
||||
@ -576,6 +613,148 @@
|
||||
<state readOnly="true" pattern="%.1f"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="air-quality-index">
|
||||
<item-type>Number</item-type>
|
||||
<label>Air Quality Index</label>
|
||||
<description>Current air quality index.</description>
|
||||
<state readOnly="true" pattern="%.0f">
|
||||
<options>
|
||||
<option value="1">Good</option>
|
||||
<option value="2">Fair</option>
|
||||
<option value="3">Moderate</option>
|
||||
<option value="4">Poor</option>
|
||||
<option value="5">Very Poor</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="forecasted-air-quality-index">
|
||||
<item-type>Number</item-type>
|
||||
<label>Forecasted Air Quality Index</label>
|
||||
<description>Forecasted air quality index.</description>
|
||||
<state readOnly="true" pattern="%.0f">
|
||||
<options>
|
||||
<option value="1">Good</option>
|
||||
<option value="2">Fair</option>
|
||||
<option value="3">Moderate</option>
|
||||
<option value="4">Poor</option>
|
||||
<option value="5">Very Poor</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="particulate-matter-2dot5">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Particulate Matter - PM2.5</label>
|
||||
<description>Current density of particles less than 2.5 µm in diameter.</description>
|
||||
<state readOnly="true" pattern="%.2f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="forecasted-particulate-matter-2dot5">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Forecasted Particulate Matter - PM2.5</label>
|
||||
<description>Forecasted density of particles less than 2.5 µm in diameter.</description>
|
||||
<state readOnly="true" pattern="%.2f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="forecasted-particulate-matter-10">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Particulate Matter - PM10</label>
|
||||
<description>Current density of particles less than 10 µm in diameter.</description>
|
||||
<state readOnly="true" pattern="%.2f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="particulate-matter-10">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Forecasted Particulate Matter - PM10</label>
|
||||
<description>Forecasted density of particles less than 10 µm in diameter.</description>
|
||||
<state readOnly="true" pattern="%.2f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="carbon-monoxide">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Carbon Monoxide</label>
|
||||
<description>Current concentration of carbon monoxide.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="forecasted-carbon-monoxide">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Forecasted Carbon Monoxide</label>
|
||||
<description>Forecasted concentration of carbon monoxide.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="nitrogen-monoxide">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Nitrogen Monoxide</label>
|
||||
<description>Current concentration of nitrogen monoxide.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="forecasted-nitrogen-monoxide">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Forecasted Nitrogen Monoxide</label>
|
||||
<description>Forecasted concentration of nitrogen monoxide.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="nitrogen-dioxide">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Nitrogen Dioxide</label>
|
||||
<description>Current concentration of nitrogen dioxide.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="forecasted-nitrogen-dioxide">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Forecasted Nitrogen Dioxide</label>
|
||||
<description>Forecasted concentration of nitrogen dioxide.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ozone">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Ozone</label>
|
||||
<description>Current concentration of ozone.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="forecasted-ozone">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Forecasted Ozone</label>
|
||||
<description>Forecasted concentration of ozone.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="sulphur-dioxide">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Sulphur Dioxide</label>
|
||||
<description>Current concentration of sulphur dioxide.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="forecasted-sulphur-dioxide">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Forecasted Sulphur Dioxide</label>
|
||||
<description>Forecasted concentration of sulphur dioxide.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ammonia">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Ammonia</label>
|
||||
<description>Current concentration of ammonia.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="forecasted-ammonia">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>Forecasted Ammonia</label>
|
||||
<description>Forecasted concentration of ammonia.</description>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="visibility">
|
||||
<item-type>Number:Length</item-type>
|
||||
<label>Visibility</label>
|
||||
@ -585,9 +764,9 @@
|
||||
|
||||
<channel-type id="precip-probability">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Probability</label>
|
||||
<label>Precipitation Probability</label>
|
||||
<description>Forecasted precipitation probability.</description>
|
||||
<category>Rain</category>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
@ -116,6 +116,23 @@
|
||||
<config-description-ref uri="thing-type:openweathermap:uvindex"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="air-pollution">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="weather-api"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Air Pollution</label>
|
||||
<description>Provides air pollution data from the OpenWeatherMap API.</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="current" typeId="airPollution"/>
|
||||
</channel-groups>
|
||||
|
||||
<representation-property>location</representation-property>
|
||||
|
||||
<config-description-ref uri="thing-type:openweathermap:air-pollution"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="onecall">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="weather-api"/>
|
||||
|
Loading…
Reference in New Issue
Block a user