2 * Copyright (c) 2010-2021 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.OpenWeatherMapCommunicationException;
29 import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConfigurationException;
30 import org.openhab.binding.openweathermap.internal.connection.OpenWeatherMapConnection;
31 import org.openhab.binding.openweathermap.internal.dto.onecall.Alert;
32 import org.openhab.binding.openweathermap.internal.dto.onecall.FeelsLike;
33 import org.openhab.binding.openweathermap.internal.dto.onecall.OpenWeatherMapOneCallAPIData;
34 import org.openhab.binding.openweathermap.internal.dto.onecall.Rain;
35 import org.openhab.binding.openweathermap.internal.dto.onecall.Snow;
36 import org.openhab.binding.openweathermap.internal.dto.onecall.Temp;
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 OpenWeatherMapCommunicationException, OpenWeatherMapConfigurationException {
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.getLocalizedMessage(), 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().size() > count) {
386 org.openhab.binding.openweathermap.internal.dto.onecall.Minutely forecastData = localWeatherData
387 .getMinutely().get(count);
388 State state = UnDefType.UNDEF;
390 case CHANNEL_TIME_STAMP:
391 state = getDateTimeTypeState(forecastData.getDt());
393 case CHANNEL_PRECIPITATION:
394 double precipitation = forecastData.getPrecipitation();
395 state = getQuantityTypeState(precipitation, MILLI(METRE));
398 // This should not happen
399 logger.warn("Unknown channel id {} in onecall minutely weather data", channelId);
402 logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
403 updateState(channelUID, state);
405 logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
410 * Update the channel from the last OpenWeatherMap data retrieved.
412 * @param channelUID the id identifying the channel to be updated
413 * @param count the number of the hour referenced by the channel
415 private void updateHourlyForecastChannel(ChannelUID channelUID, int count) {
416 String channelId = channelUID.getIdWithoutGroup();
417 String channelGroupId = channelUID.getGroupId();
418 if (forecastHours == 0) {
420 "Can't update channel group {} because forecastHours is set to '0'. Please adjust config accordingly",
424 OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
425 if (localWeatherData != null && localWeatherData.getHourly().size() > count) {
426 org.openhab.binding.openweathermap.internal.dto.onecall.Hourly forecastData = localWeatherData.getHourly()
428 State state = UnDefType.UNDEF;
430 case CHANNEL_TIME_STAMP:
431 state = getDateTimeTypeState(forecastData.getDt());
433 case CHANNEL_CONDITION:
434 if (!forecastData.getWeather().isEmpty()) {
435 state = getStringTypeState(forecastData.getWeather().get(0).getDescription());
438 case CHANNEL_CONDITION_ID:
439 if (!forecastData.getWeather().isEmpty()) {
440 state = getStringTypeState(Integer.toString(forecastData.getWeather().get(0).getId()));
443 case CHANNEL_CONDITION_ICON:
444 if (!forecastData.getWeather().isEmpty()) {
445 state = getRawTypeState(
446 OpenWeatherMapConnection.getWeatherIcon(forecastData.getWeather().get(0).getIcon()));
449 case CHANNEL_CONDITION_ICON_ID:
450 if (!forecastData.getWeather().isEmpty()) {
451 state = getStringTypeState(forecastData.getWeather().get(0).getIcon());
454 case CHANNEL_TEMPERATURE:
455 state = getQuantityTypeState(forecastData.getTemp(), CELSIUS);
457 case CHANNEL_APPARENT_TEMPERATURE:
458 state = getQuantityTypeState(forecastData.getFeelsLike(), CELSIUS);
460 case CHANNEL_PRESSURE:
461 state = getQuantityTypeState(forecastData.getPressure(), HECTO(PASCAL));
463 case CHANNEL_HUMIDITY:
464 state = getQuantityTypeState(forecastData.getHumidity(), PERCENT);
466 case CHANNEL_DEW_POINT:
467 state = getQuantityTypeState(forecastData.getDewPoint(), CELSIUS);
469 case CHANNEL_WIND_SPEED:
470 state = getQuantityTypeState(forecastData.getWindSpeed(), METRE_PER_SECOND);
472 case CHANNEL_WIND_DIRECTION:
473 state = getQuantityTypeState(forecastData.getWindDeg(), DEGREE_ANGLE);
475 case CHANNEL_GUST_SPEED:
476 state = getQuantityTypeState(forecastData.getWindGust(), METRE_PER_SECOND);
478 case CHANNEL_CLOUDINESS:
479 state = getQuantityTypeState(forecastData.getClouds(), PERCENT);
481 case CHANNEL_VISIBILITY:
482 State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
483 .toUnit(KILO(METRE));
484 state = (tempstate == null ? state : tempstate);
485 case CHANNEL_PRECIP_PROBABILITY:
486 state = getQuantityTypeState(forecastData.getPop() * 100.0, PERCENT);
489 Rain rain = forecastData.getRain();
490 state = getQuantityTypeState(rain == null ? 0 : rain.get1h(), MILLI(METRE));
493 Snow snow = forecastData.getSnow();
494 state = getQuantityTypeState(snow == null ? 0 : snow.get1h(), MILLI(METRE));
497 // This should not happen
498 logger.warn("Unknown channel id {} in onecall hourly weather data", channelId);
501 logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
502 updateState(channelUID, state);
504 logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
509 * Update the channel from the last OpenWeatherMap data retrieved.
511 * @param channelUID the id identifying the channel to be updated
514 private void updateDailyForecastChannel(ChannelUID channelUID, int count) {
515 String channelId = channelUID.getIdWithoutGroup();
516 String channelGroupId = channelUID.getGroupId();
517 if (forecastDays == 0) {
519 "Can't update channel group {} because forecastDays is set to '0'. Please adjust config accordingly",
523 OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
524 if (localWeatherData != null && localWeatherData.getDaily().size() > count) {
525 org.openhab.binding.openweathermap.internal.dto.onecall.Daily forecastData = localWeatherData.getDaily()
527 State state = UnDefType.UNDEF;
531 case CHANNEL_TIME_STAMP:
532 state = getDateTimeTypeState(forecastData.getDt());
534 case CHANNEL_SUNRISE:
535 state = getDateTimeTypeState(forecastData.getSunrise());
538 state = getDateTimeTypeState(forecastData.getSunset());
540 case CHANNEL_CONDITION:
541 if (!forecastData.getWeather().isEmpty()) {
542 state = getStringTypeState(forecastData.getWeather().get(0).getDescription());
545 case CHANNEL_CONDITION_ID:
546 if (!forecastData.getWeather().isEmpty()) {
547 state = getStringTypeState(Integer.toString(forecastData.getWeather().get(0).getId()));
550 case CHANNEL_CONDITION_ICON:
551 if (!forecastData.getWeather().isEmpty()) {
552 state = getRawTypeState(
553 OpenWeatherMapConnection.getWeatherIcon(forecastData.getWeather().get(0).getIcon()));
556 case CHANNEL_CONDITION_ICON_ID:
557 if (!forecastData.getWeather().isEmpty()) {
558 state = getStringTypeState(forecastData.getWeather().get(0).getIcon());
561 case CHANNEL_MIN_TEMPERATURE:
562 temp = forecastData.getTemp();
564 state = getQuantityTypeState(temp.getMin(), CELSIUS);
567 case CHANNEL_MAX_TEMPERATURE:
568 temp = forecastData.getTemp();
570 state = getQuantityTypeState(temp.getMax(), CELSIUS);
573 case CHANNEL_MORNING_TEMPERATURE:
574 temp = forecastData.getTemp();
576 state = getQuantityTypeState(temp.getMorn(), CELSIUS);
579 case CHANNEL_DAY_TEMPERATURE:
580 temp = forecastData.getTemp();
582 state = getQuantityTypeState(temp.getDay(), CELSIUS);
585 case CHANNEL_EVENING_TEMPERATURE:
586 temp = forecastData.getTemp();
588 state = getQuantityTypeState(temp.getEve(), CELSIUS);
591 case CHANNEL_NIGHT_TEMPERATURE:
592 temp = forecastData.getTemp();
594 state = getQuantityTypeState(temp.getNight(), CELSIUS);
598 case CHANNEL_APPARENT_DAY:
599 feelsLike = forecastData.getFeelsLike();
600 if (feelsLike != null) {
601 state = getQuantityTypeState(feelsLike.getDay(), CELSIUS);
604 case CHANNEL_APPARENT_MORNING:
605 feelsLike = forecastData.getFeelsLike();
606 if (feelsLike != null) {
607 state = getQuantityTypeState(feelsLike.getMorn(), CELSIUS);
610 case CHANNEL_APPARENT_EVENING:
611 feelsLike = forecastData.getFeelsLike();
612 if (feelsLike != null) {
613 state = getQuantityTypeState(feelsLike.getEve(), CELSIUS);
616 case CHANNEL_APPARENT_NIGHT:
617 feelsLike = forecastData.getFeelsLike();
618 if (feelsLike != null) {
619 state = getQuantityTypeState(feelsLike.getNight(), CELSIUS);
622 case CHANNEL_PRESSURE:
623 state = getQuantityTypeState(forecastData.getPressure(), HECTO(PASCAL));
625 case CHANNEL_HUMIDITY:
626 state = getQuantityTypeState(forecastData.getHumidity(), PERCENT);
628 case CHANNEL_WIND_SPEED:
629 state = getQuantityTypeState(forecastData.getWindSpeed(), METRE_PER_SECOND);
631 case CHANNEL_WIND_DIRECTION:
632 state = getQuantityTypeState(forecastData.getWindDeg(), DEGREE_ANGLE);
634 case CHANNEL_GUST_SPEED:
635 state = getQuantityTypeState(forecastData.getWindGust(), METRE_PER_SECOND);
637 case CHANNEL_CLOUDINESS:
638 state = getQuantityTypeState(forecastData.getClouds(), PERCENT);
640 case CHANNEL_DEW_POINT:
641 state = getQuantityTypeState(forecastData.getDewPoint(), CELSIUS);
643 case CHANNEL_UVINDEX:
644 state = getDecimalTypeState(forecastData.getUvi());
646 case CHANNEL_VISIBILITY:
647 State tempstate = new QuantityType<>(localWeatherData.getCurrent().getVisibility(), METRE)
648 .toUnit(KILO(METRE));
649 state = (tempstate == null ? state : tempstate);
650 case CHANNEL_PRECIP_PROBABILITY:
651 state = getQuantityTypeState(forecastData.getPop() * 100.0, PERCENT);
654 state = getQuantityTypeState(forecastData.getRain(), MILLI(METRE));
657 state = getQuantityTypeState(forecastData.getSnow(), MILLI(METRE));
660 // This should not happen
661 logger.warn("Unknown channel id {} in onecall daily weather data", channelId);
664 logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
665 updateState(channelUID, state);
667 logger.debug("No weather data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
672 * Update the channel from the last OpenWeaterhMap data retrieved.
674 * @param channelUID the id identifying the channel to be updated
677 private void updateAlertsChannel(ChannelUID channelUID, int count) {
678 String channelId = channelUID.getIdWithoutGroup();
679 String channelGroupId = channelUID.getGroupId();
680 OpenWeatherMapOneCallAPIData localWeatherData = weatherData;
681 List<Alert> alerts = localWeatherData != null ? localWeatherData.alerts : null;
682 State state = UnDefType.UNDEF;
683 if (alerts != null && alerts.size() > count) {
684 Alert alert = alerts.get(count - 1);
686 case CHANNEL_ALERT_EVENT:
687 state = getStringTypeState(alert.event);
689 case CHANNEL_ALERT_DESCRIPTION:
690 state = getStringTypeState(alert.description);
692 case CHANNEL_ALERT_ONSET:
693 state = getDateTimeTypeState(alert.start);
695 case CHANNEL_ALERT_EXPIRES:
696 state = getDateTimeTypeState(alert.end);
698 case CHANNEL_ALERT_SOURCE:
699 state = getStringTypeState(alert.senderName);
702 logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
704 logger.debug("No data available to update channel '{}' of group '{}'.", channelId, channelGroupId);
706 updateState(channelUID, state);