2 * Copyright (c) 2010-2022 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.openweathermap.internal.handler;
15 import static org.openhab.binding.openweathermap.internal.OpenWeatherMapBindingConstants.*;
16 import static org.openhab.core.library.unit.MetricPrefix.*;
17 import static org.openhab.core.library.unit.SIUnits.*;
18 import static org.openhab.core.library.unit.Units.*;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.openhab.binding.openweathermap.internal.config.OpenWeatherMapOneCallConfiguration;
28 import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConnection;
29 import org.openhab.binding.openweathermap.internal.dto.onecall.Alert;
30 import org.openhab.binding.openweathermap.internal.dto.onecall.FeelsLike;
31 import org.openhab.binding.openweathermap.internal.dto.onecall.OpenWeatherMapOneCallAPIData;
32 import org.openhab.binding.openweathermap.internal.dto.onecall.Rain;
33 import org.openhab.binding.openweathermap.internal.dto.onecall.Snow;
34 import org.openhab.binding.openweathermap.internal.dto.onecall.Temp;
35 import org.openhab.core.i18n.CommunicationException;
36 import org.openhab.core.i18n.ConfigurationException;
37 import org.openhab.core.i18n.TimeZoneProvider;
38 import org.openhab.core.library.types.QuantityType;
39 import org.openhab.core.thing.Channel;
40 import org.openhab.core.thing.ChannelUID;
41 import org.openhab.core.thing.Thing;
42 import org.openhab.core.thing.ThingStatus;
43 import org.openhab.core.thing.ThingStatusDetail;
44 import org.openhab.core.thing.binding.builder.ThingBuilder;
45 import org.openhab.core.types.State;
46 import org.openhab.core.types.UnDefType;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 import com.google.gson.JsonSyntaxException;
53 * The {@link OpenWeatherMapOneCallHandler} is responsible for handling commands, which are sent to one of
56 * @author Wolfgang Klimt - Initial contribution
57 * @author Christoph Weitkamp - Added weather alerts
60 public class OpenWeatherMapOneCallHandler extends AbstractOpenWeatherMapHandler {
62 private final Logger logger = LoggerFactory.getLogger(OpenWeatherMapOneCallHandler.class);
64 private static final String CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX = "forecastMinutes";
65 private static final String CHANNEL_GROUP_HOURLY_FORECAST_PREFIX = "forecastHours";
66 private static final String CHANNEL_GROUP_DAILY_FORECAST_PREFIX = "forecastDay";
67 private static final String CHANNEL_GROUP_ALERTS_PREFIX = "alerts";
68 private static final Pattern CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN = Pattern
69 .compile(CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + "([0-9]*)");
70 private static final Pattern CHANNEL_GROUP_DAILY_FORECAST_PREFIX_PATTERN = Pattern
71 .compile(CHANNEL_GROUP_DAILY_FORECAST_PREFIX + "([0-9]*)");
72 private static final Pattern CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX_PATTERN = Pattern
73 .compile(CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX + "([0-9]*)");
74 private static final Pattern CHANNEL_GROUP_ALERTS_PREFIX_PATTERN = Pattern
75 .compile(CHANNEL_GROUP_ALERTS_PREFIX + "([0-9]*)");
77 private @Nullable OpenWeatherMapOneCallAPIData weatherData;
79 private int forecastMinutes = 60;
80 private int forecastHours = 24;
81 private int forecastDays = 8;
82 private int numberOfAlerts = 0;
84 public OpenWeatherMapOneCallHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
85 super(thing, timeZoneProvider);
89 public void initialize() {
91 logger.debug("Initialize OpenWeatherMapOneCallHandler handler '{}'.", getThing().getUID());
92 OpenWeatherMapOneCallConfiguration config = getConfigAs(OpenWeatherMapOneCallConfiguration.class);
94 boolean configValid = true;
95 int newForecastMinutes = config.forecastMinutes;
96 if (newForecastMinutes < 0 || newForecastMinutes > 60) {
97 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
98 "@text/offline.conf-error-not-supported-onecall-number-of-minutes");
101 int newForecastHours = config.forecastHours;
102 if (newForecastHours < 0 || newForecastHours > 48) {
103 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
104 "@text/offline.conf-error-not-supported-onecall-number-of-hours");
107 int newForecastDays = config.forecastDays;
108 if (newForecastDays < 0 || newForecastDays > 8) {
109 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
110 "@text/offline.conf-error-not-supported-onecall-number-of-days");
113 int newNumberOfAlerts = config.numberOfAlerts;
114 if (newNumberOfAlerts < 0) {
115 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
116 "@text/offline.conf-error-not-supported-onecall-number-of-alerts");
121 logger.debug("Rebuilding thing '{}'.", getThing().getUID());
122 List<Channel> toBeAddedChannels = new ArrayList<>();
123 List<Channel> toBeRemovedChannels = new ArrayList<>();
125 .addAll(createChannelsForGroup(CHANNEL_GROUP_ONECALL_CURRENT, CHANNEL_GROUP_TYPE_ONECALL_CURRENT));
126 if (forecastMinutes != newForecastMinutes) {
127 logger.debug("forecastMinutes changed from {} to {}. Rebuilding minutely forecast channel groups.",
128 forecastMinutes, newForecastMinutes);
129 if (forecastMinutes > newForecastMinutes) {
130 for (int i = newForecastMinutes + 1; i <= forecastMinutes; i++) {
131 toBeRemovedChannels.addAll(removeChannelsOfGroup(
132 CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i)));
135 for (int i = forecastMinutes + 1; i <= newForecastMinutes; i++) {
136 toBeAddedChannels.addAll(createChannelsForGroup(
137 CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i),
138 CHANNEL_GROUP_TYPE_ONECALL_MINUTELY_FORECAST));
141 forecastMinutes = newForecastMinutes;
143 if (forecastHours != newForecastHours) {
144 logger.debug("ForecastHours changed from {} to {}. Rebuilding hourly forecast channel groups.",
145 forecastHours, newForecastHours);
146 if (forecastHours > newForecastHours) {
147 for (int i = newForecastHours + 1; i <= forecastHours; i++) {
148 toBeRemovedChannels.addAll(removeChannelsOfGroup(
149 CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i)));
152 for (int i = forecastHours + 1; i <= newForecastHours; i++) {
153 toBeAddedChannels.addAll(createChannelsForGroup(
154 CHANNEL_GROUP_HOURLY_FORECAST_PREFIX + ((i < 10) ? "0" : "") + Integer.toString(i),
155 CHANNEL_GROUP_TYPE_ONECALL_HOURLY_FORECAST));
158 forecastHours = newForecastHours;
160 if (forecastDays != newForecastDays) {
161 logger.debug("ForecastDays changed from {} to {}. Rebuilding daily forecast channel groups.",
162 forecastDays, newForecastDays);
163 if (forecastDays > newForecastDays) {
164 if (newForecastDays < 1) {
165 toBeRemovedChannels.addAll(removeChannelsOfGroup(CHANNEL_GROUP_FORECAST_TODAY));
167 if (newForecastDays < 2) {
168 toBeRemovedChannels.addAll(removeChannelsOfGroup(CHANNEL_GROUP_FORECAST_TOMORROW));
170 for (int i = newForecastDays; i < forecastDays; ++i) {
171 toBeRemovedChannels.addAll(
172 removeChannelsOfGroup(CHANNEL_GROUP_DAILY_FORECAST_PREFIX + Integer.toString(i)));
175 if (forecastDays == 0 && newForecastDays > 0) {
176 toBeAddedChannels.addAll(createChannelsForGroup(CHANNEL_GROUP_FORECAST_TODAY,
177 CHANNEL_GROUP_TYPE_ONECALL_DAILY_FORECAST));
179 if (forecastDays <= 1 && newForecastDays > 1) {
180 toBeAddedChannels.addAll(createChannelsForGroup(CHANNEL_GROUP_FORECAST_TOMORROW,
181 CHANNEL_GROUP_TYPE_ONECALL_DAILY_FORECAST));
183 for (int i = Math.max(forecastDays, 2); i < newForecastDays; ++i) {
184 toBeAddedChannels.addAll(
185 createChannelsForGroup(CHANNEL_GROUP_DAILY_FORECAST_PREFIX + Integer.toString(i),
186 CHANNEL_GROUP_TYPE_ONECALL_DAILY_FORECAST));
189 forecastDays = newForecastDays;
190 if (numberOfAlerts != newNumberOfAlerts) {
191 logger.debug("Rebuilding alerts channel groups.");
192 if (numberOfAlerts > newNumberOfAlerts) {
193 for (int i = newNumberOfAlerts + 1; i <= numberOfAlerts; ++i) {
195 .addAll(removeChannelsOfGroup(CHANNEL_GROUP_ALERTS_PREFIX + Integer.toString(i)));
198 for (int i = numberOfAlerts + 1; i <= newNumberOfAlerts; ++i) {
200 .addAll(createChannelsForGroup(CHANNEL_GROUP_ALERTS_PREFIX + Integer.toString(i),
201 CHANNEL_GROUP_TYPE_ONECALL_ALERTS));
204 numberOfAlerts = newNumberOfAlerts;
207 logger.debug("toBeRemovedChannels: {}. toBeAddedChannels: {}", toBeRemovedChannels, toBeAddedChannels);
208 ThingBuilder builder = editThing().withoutChannels(toBeRemovedChannels);
209 for (Channel channel : toBeAddedChannels) {
210 builder.withChannel(channel);
212 updateThing(builder.build());
217 protected boolean requestData(OpenWeatherMapConnection connection)
218 throws CommunicationException, ConfigurationException {
219 logger.debug("Update weather and forecast data of thing '{}'.", getThing().getUID());
221 weatherData = connection.getOneCallAPIData(location, forecastMinutes == 0, forecastHours == 0,
222 forecastDays == 0, numberOfAlerts == 0);
224 } catch (JsonSyntaxException e) {
225 logger.debug("JsonSyntaxException occurred during execution: {}", e.getMessage(), e);
231 protected void updateChannel(ChannelUID channelUID) {
232 String channelGroupId = channelUID.getGroupId();
233 logger.debug("OneCallHandler: updateChannel {}, groupID {}", channelUID, channelGroupId);
234 switch (channelGroupId) {
235 case CHANNEL_GROUP_ONECALL_CURRENT:
236 updateCurrentChannel(channelUID);
238 case CHANNEL_GROUP_ONECALL_TODAY:
239 updateDailyForecastChannel(channelUID, 0);
241 case CHANNEL_GROUP_ONECALL_TOMORROW:
242 updateDailyForecastChannel(channelUID, 1);
246 Matcher hourlyForecastMatcher = CHANNEL_GROUP_HOURLY_FORECAST_PREFIX_PATTERN.matcher(channelGroupId);
247 if (hourlyForecastMatcher.find() && (i = Integer.parseInt(hourlyForecastMatcher.group(1))) >= 1
249 updateHourlyForecastChannel(channelUID, (i - 1));
252 Matcher dailyForecastMatcher = CHANNEL_GROUP_DAILY_FORECAST_PREFIX_PATTERN.matcher(channelGroupId);
253 if (dailyForecastMatcher.find() && (i = Integer.parseInt(dailyForecastMatcher.group(1))) >= 1
255 updateDailyForecastChannel(channelUID, i);
258 Matcher minutelyForecastMatcher = CHANNEL_GROUP_MINUTELY_FORECAST_PREFIX_PATTERN
259 .matcher(channelGroupId);
260 if (minutelyForecastMatcher.find() && (i = Integer.parseInt(minutelyForecastMatcher.group(1))) >= 1
262 updateMinutelyForecastChannel(channelUID, i - 1);
265 Matcher alertsMatcher = CHANNEL_GROUP_ALERTS_PREFIX_PATTERN.matcher(channelGroupId);
266 if (alertsMatcher.find() && (i = Integer.parseInt(alertsMatcher.group(1))) >= 1) {
267 updateAlertsChannel(channelUID, i);
275 * Update the channel from the last OpenWeatherMap data retrieved.
277 * @param channelUID the id identifying the channel to be updated
279 private void updateCurrentChannel(ChannelUID channelUID) {
280 String channelId = channelUID.getIdWithoutGroup();
281 String channelGroupId = channelUID.getGroupId();
282 OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
283 if (localWeatherData != null) {
284 State state = UnDefType.UNDEF;
286 case CHANNEL_STATION_LOCATION:
287 state = getPointTypeState(localWeatherData.getLat(), localWeatherData.getLon());
289 case CHANNEL_TIME_STAMP:
290 state = getDateTimeTypeState(localWeatherData.getCurrent().getDt());
292 case CHANNEL_SUNRISE:
293 state = getDateTimeTypeState(localWeatherData.getCurrent().getSunrise());
296 state = getDateTimeTypeState(localWeatherData.getCurrent().getSunset());
298 case CHANNEL_CONDITION:
299 if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
300 state = getStringTypeState(localWeatherData.getCurrent().getWeather().get(0).getDescription());
303 case CHANNEL_CONDITION_ID:
304 if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
305 state = getStringTypeState(
306 Integer.toString(localWeatherData.getCurrent().getWeather().get(0).getId()));
309 case CHANNEL_CONDITION_ICON:
310 if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
311 state = getRawTypeState(OpenWeatherMapConnection
312 .getWeatherIcon(localWeatherData.getCurrent().getWeather().get(0).getIcon()));
315 case CHANNEL_CONDITION_ICON_ID:
316 if (!localWeatherData.getCurrent().getWeather().isEmpty()) {
317 state = getStringTypeState(localWeatherData.getCurrent().getWeather().get(0).getIcon());
320 case CHANNEL_TEMPERATURE:
321 state = getQuantityTypeState(localWeatherData.getCurrent().getTemp(), CELSIUS);
323 case CHANNEL_APPARENT_TEMPERATURE:
324 state = getQuantityTypeState(localWeatherData.getCurrent().getFeelsLike(), CELSIUS);
326 case CHANNEL_PRESSURE:
327 state = getQuantityTypeState(localWeatherData.getCurrent().getPressure(), HECTO(PASCAL));
329 case CHANNEL_HUMIDITY:
330 state = getQuantityTypeState(localWeatherData.getCurrent().getHumidity(), PERCENT);
332 case CHANNEL_DEW_POINT:
333 state = getQuantityTypeState(localWeatherData.getCurrent().getDewPoint(), CELSIUS);
335 case CHANNEL_WIND_SPEED:
336 state = getQuantityTypeState(localWeatherData.getCurrent().getWindSpeed(), METRE_PER_SECOND);
338 case CHANNEL_WIND_DIRECTION:
339 state = getQuantityTypeState(localWeatherData.getCurrent().getWindDeg(), DEGREE_ANGLE);
341 case CHANNEL_GUST_SPEED:
342 state = getQuantityTypeState(localWeatherData.getCurrent().getWindGust(), METRE_PER_SECOND);
344 case CHANNEL_CLOUDINESS:
345 state = getQuantityTypeState(localWeatherData.getCurrent().getClouds(), PERCENT);
347 case CHANNEL_UVINDEX:
348 state = getDecimalTypeState(localWeatherData.getCurrent().getUvi());
351 Rain rain = localWeatherData.getCurrent().getRain();
352 state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
355 Snow snow = localWeatherData.getCurrent().getSnow();
356 state = getQuantityTypeState(snow == null ? 0 : snow.get1h(), MILLI(METRE));
358 case CHANNEL_VISIBILITY:
359 State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
360 .toUnit(KILO(METRE));
361 state = (tempstate == null ? state : tempstate);
364 // This should not happen
365 logger.warn("Unknown channel id {} in onecall current weather data", channelId);
368 logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
369 updateState(channelUID, state);
371 logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
375 private void updateMinutelyForecastChannel(ChannelUID channelUID, int count) {
376 String channelId = channelUID.getIdWithoutGroup();
377 String channelGroupId = channelUID.getGroupId();
378 OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
379 if (forecastMinutes == 0) {
381 "Can't update channel group {} because forecastMinutes is set to '0'. Please adjust config accordingly",
385 if (localWeatherData != null && localWeatherData.getMinutely() != null
386 && localWeatherData.getMinutely().size() > count) {
387 org.openhab.binding.openweathermap.internal.dto.onecall.Minutely forecastData = localWeatherData
388 .getMinutely().get(count);
389 State state = UnDefType.UNDEF;
391 case CHANNEL_TIME_STAMP:
392 state = getDateTimeTypeState(forecastData.getDt());
394 case CHANNEL_PRECIPITATION:
395 double precipitation = forecastData.getPrecipitation();
396 state = getQuantityTypeState(precipitation, MILLI(METRE));
399 // This should not happen
400 logger.warn("Unknown channel id {} in onecall minutely weather data", channelId);
403 logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
404 updateState(channelUID, state);
406 logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
411 * Update the channel from the last OpenWeatherMap data retrieved.
413 * @param channelUID the id identifying the channel to be updated
414 * @param count the number of the hour referenced by the channel
416 private void updateHourlyForecastChannel(ChannelUID channelUID, int count) {
417 String channelId = channelUID.getIdWithoutGroup();
418 String channelGroupId = channelUID.getGroupId();
419 if (forecastHours == 0) {
421 "Can't update channel group {} because forecastHours is set to '0'. Please adjust config accordingly",
425 OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
426 if (localWeatherData != null && localWeatherData.getHourly().size() > count) {
427 org.openhab.binding.openweathermap.internal.dto.onecall.Hourly forecastData = localWeatherData.getHourly()
429 State state = UnDefType.UNDEF;
431 case CHANNEL_TIME_STAMP:
432 state = getDateTimeTypeState(forecastData.getDt());
434 case CHANNEL_CONDITION:
435 if (!forecastData.getWeather().isEmpty()) {
436 state = getStringTypeState(forecastData.getWeather().get(0).getDescription());
439 case CHANNEL_CONDITION_ID:
440 if (!forecastData.getWeather().isEmpty()) {
441 state = getStringTypeState(Integer.toString(forecastData.getWeather().get(0).getId()));
444 case CHANNEL_CONDITION_ICON:
445 if (!forecastData.getWeather().isEmpty()) {
446 state = getRawTypeState(
447 OpenWeatherMapConnection.getWeatherIcon(forecastData.getWeather().get(0).getIcon()));
450 case CHANNEL_CONDITION_ICON_ID:
451 if (!forecastData.getWeather().isEmpty()) {
452 state = getStringTypeState(forecastData.getWeather().get(0).getIcon());
455 case CHANNEL_TEMPERATURE:
456 state = getQuantityTypeState(forecastData.getTemp(), CELSIUS);
458 case CHANNEL_APPARENT_TEMPERATURE:
459 state = getQuantityTypeState(forecastData.getFeelsLike(), CELSIUS);
461 case CHANNEL_PRESSURE:
462 state = getQuantityTypeState(forecastData.getPressure(), HECTO(PASCAL));
464 case CHANNEL_HUMIDITY:
465 state = getQuantityTypeState(forecastData.getHumidity(), PERCENT);
467 case CHANNEL_DEW_POINT:
468 state = getQuantityTypeState(forecastData.getDewPoint(), CELSIUS);
470 case CHANNEL_WIND_SPEED:
471 state = getQuantityTypeState(forecastData.getWindSpeed(), METRE_PER_SECOND);
473 case CHANNEL_WIND_DIRECTION:
474 state = getQuantityTypeState(forecastData.getWindDeg(), DEGREE_ANGLE);
476 case CHANNEL_GUST_SPEED:
477 state = getQuantityTypeState(forecastData.getWindGust(), METRE_PER_SECOND);
479 case CHANNEL_CLOUDINESS:
480 state = getQuantityTypeState(forecastData.getClouds(), PERCENT);
482 case CHANNEL_VISIBILITY:
483 State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
484 .toUnit(KILO(METRE));
485 state = (tempstate == null ? state : tempstate);
486 case CHANNEL_PRECIP_PROBABILITY:
487 state = getQuantityTypeState(forecastData.getPop() * 100.0, PERCENT);
490 Rain rain = forecastData.getRain();
491 state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
494 Snow snow = forecastData.getSnow();
495 state = getQuantityTypeState(snow == null ? 0 : snow.get1h(), MILLI(METRE));
498 // This should not happen
499 logger.warn("Unknown channel id {} in onecall hourly weather data", channelId);
502 logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
503 updateState(channelUID, state);
505 logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
510 * Update the channel from the last OpenWeatherMap data retrieved.
512 * @param channelUID the id identifying the channel to be updated
515 private void updateDailyForecastChannel(ChannelUID channelUID, int count) {
516 String channelId = channelUID.getIdWithoutGroup();
517 String channelGroupId = channelUID.getGroupId();
518 if (forecastDays == 0) {
520 "Can't update channel group {} because forecastDays is set to '0'. Please adjust config accordingly",
524 OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
525 if (localWeatherData != null && localWeatherData.getDaily().size() > count) {
526 org.openhab.binding.openweathermap.internal.dto.onecall.Daily forecastData = localWeatherData.getDaily()
528 State state = UnDefType.UNDEF;
532 case CHANNEL_TIME_STAMP:
533 state = getDateTimeTypeState(forecastData.getDt());
535 case CHANNEL_SUNRISE:
536 state = getDateTimeTypeState(forecastData.getSunrise());
539 state = getDateTimeTypeState(forecastData.getSunset());
541 case CHANNEL_CONDITION:
542 if (!forecastData.getWeather().isEmpty()) {
543 state = getStringTypeState(forecastData.getWeather().get(0).getDescription());
546 case CHANNEL_CONDITION_ID:
547 if (!forecastData.getWeather().isEmpty()) {
548 state = getStringTypeState(Integer.toString(forecastData.getWeather().get(0).getId()));
551 case CHANNEL_CONDITION_ICON:
552 if (!forecastData.getWeather().isEmpty()) {
553 state = getRawTypeState(
554 OpenWeatherMapConnection.getWeatherIcon(forecastData.getWeather().get(0).getIcon()));
557 case CHANNEL_CONDITION_ICON_ID:
558 if (!forecastData.getWeather().isEmpty()) {
559 state = getStringTypeState(forecastData.getWeather().get(0).getIcon());
562 case CHANNEL_MIN_TEMPERATURE:
563 temp = forecastData.getTemp();
565 state = getQuantityTypeState(temp.getMin(), CELSIUS);
568 case CHANNEL_MAX_TEMPERATURE:
569 temp = forecastData.getTemp();
571 state = getQuantityTypeState(temp.getMax(), CELSIUS);
574 case CHANNEL_MORNING_TEMPERATURE:
575 temp = forecastData.getTemp();
577 state = getQuantityTypeState(temp.getMorn(), CELSIUS);
580 case CHANNEL_DAY_TEMPERATURE:
581 temp = forecastData.getTemp();
583 state = getQuantityTypeState(temp.getDay(), CELSIUS);
586 case CHANNEL_EVENING_TEMPERATURE:
587 temp = forecastData.getTemp();
589 state = getQuantityTypeState(temp.getEve(), CELSIUS);
592 case CHANNEL_NIGHT_TEMPERATURE:
593 temp = forecastData.getTemp();
595 state = getQuantityTypeState(temp.getNight(), CELSIUS);
599 case CHANNEL_APPARENT_DAY:
600 feelsLike = forecastData.getFeelsLike();
601 if (feelsLike != null) {
602 state = getQuantityTypeState(feelsLike.getDay(), CELSIUS);
605 case CHANNEL_APPARENT_MORNING:
606 feelsLike = forecastData.getFeelsLike();
607 if (feelsLike != null) {
608 state = getQuantityTypeState(feelsLike.getMorn(), CELSIUS);
611 case CHANNEL_APPARENT_EVENING:
612 feelsLike = forecastData.getFeelsLike();
613 if (feelsLike != null) {
614 state = getQuantityTypeState(feelsLike.getEve(), CELSIUS);
617 case CHANNEL_APPARENT_NIGHT:
618 feelsLike = forecastData.getFeelsLike();
619 if (feelsLike != null) {
620 state = getQuantityTypeState(feelsLike.getNight(), CELSIUS);
623 case CHANNEL_PRESSURE:
624 state = getQuantityTypeState(forecastData.getPressure(), HECTO(PASCAL));
626 case CHANNEL_HUMIDITY:
627 state = getQuantityTypeState(forecastData.getHumidity(), PERCENT);
629 case CHANNEL_WIND_SPEED:
630 state = getQuantityTypeState(forecastData.getWindSpeed(), METRE_PER_SECOND);
632 case CHANNEL_WIND_DIRECTION:
633 state = getQuantityTypeState(forecastData.getWindDeg(), DEGREE_ANGLE);
635 case CHANNEL_GUST_SPEED:
636 state = getQuantityTypeState(forecastData.getWindGust(), METRE_PER_SECOND);
638 case CHANNEL_CLOUDINESS:
639 state = getQuantityTypeState(forecastData.getClouds(), PERCENT);
641 case CHANNEL_DEW_POINT:
642 state = getQuantityTypeState(forecastData.getDewPoint(), CELSIUS);
644 case CHANNEL_UVINDEX:
645 state = getDecimalTypeState(forecastData.getUvi());
647 case CHANNEL_VISIBILITY:
648 State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
649 .toUnit(KILO(METRE));
650 state = (tempstate == null ? state : tempstate);
651 case CHANNEL_PRECIP_PROBABILITY:
652 state = getQuantityTypeState(forecastData.getPop() * 100.0, PERCENT);
655 state = getQuantityTypeState(forecastData.getRain(), MILLI(METRE));
658 state = getQuantityTypeState(forecastData.getSnow(), MILLI(METRE));
661 // This should not happen
662 logger.warn("Unknown channel id {} in onecall daily weather data", channelId);
665 logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
666 updateState(channelUID, state);
668 logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
673 * Update the channel from the last OpenWeaterhMap data retrieved.
675 * @param channelUID the id identifying the channel to be updated
678 private void updateAlertsChannel(ChannelUID channelUID, int count) {
679 String channelId = channelUID.getIdWithoutGroup();
680 String channelGroupId = channelUID.getGroupId();
681 OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
682 List<Alert> alerts = localWeatherData != null ? localWeatherData.alerts : null;
683 State state = UnDefType.UNDEF;
684 if (alerts != null && alerts.size() > count) {
685 Alert alert = alerts.get(count - 1);
687 case CHANNEL_ALERT_EVENT:
688 state = getStringTypeState(alert.event);
690 case CHANNEL_ALERT_DESCRIPTION:
691 state = getStringTypeState(alert.description);
693 case CHANNEL_ALERT_ONSET:
694 state = getDateTimeTypeState(alert.start);
696 case CHANNEL_ALERT_EXPIRES:
697 state = getDateTimeTypeState(alert.end);
699 case CHANNEL_ALERT_SOURCE:
700 state = getStringTypeState(alert.senderName);
703 logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
705 logger.debug("No data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
707 updateState(channelUID, state);