2 * Copyright (c) 2010-2023 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.ambientweather.internal.handler;
15 import java.time.Instant;
16 import java.time.ZoneId;
17 import java.time.ZonedDateTime;
18 import java.time.format.DateTimeParseException;
20 import javax.measure.Unit;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.ambientweather.internal.config.StationConfig;
25 import org.openhab.binding.ambientweather.internal.processor.ProcessorFactory;
26 import org.openhab.binding.ambientweather.internal.processor.ProcessorNotFoundException;
27 import org.openhab.core.common.AbstractUID;
28 import org.openhab.core.i18n.TimeZoneProvider;
29 import org.openhab.core.library.types.DateTimeType;
30 import org.openhab.core.library.types.DecimalType;
31 import org.openhab.core.library.types.QuantityType;
32 import org.openhab.core.library.types.StringType;
33 import org.openhab.core.thing.ChannelUID;
34 import org.openhab.core.thing.Thing;
35 import org.openhab.core.thing.ThingStatus;
36 import org.openhab.core.thing.ThingStatusDetail;
37 import org.openhab.core.thing.ThingStatusInfo;
38 import org.openhab.core.thing.binding.BaseThingHandler;
39 import org.openhab.core.types.Command;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 * The {@link AmbientWeatherStationHandler} is responsible for processing
45 * info and weather data updates.
47 * @author Mark Hilbush - Initial contribution
50 public class AmbientWeatherStationHandler extends BaseThingHandler {
51 private final Logger logger = LoggerFactory.getLogger(AmbientWeatherStationHandler.class);
53 // MAC address for weather station handled by this thing handler
54 private @Nullable String macAddress;
56 // Short name for logging station type
57 private String station;
59 // Time zone provider representing time zone configured in openHAB config
60 TimeZoneProvider timeZoneProvider;
62 public AmbientWeatherStationHandler(Thing thing, TimeZoneProvider timeZoneProvider) {
65 this.timeZoneProvider = timeZoneProvider;
67 // Name of station thing type used in logging
68 String s = thing.getThingTypeUID().getAsString();
69 station = s.substring(s.indexOf(AbstractUID.SEPARATOR) + 1).toUpperCase();
73 public void initialize() {
74 macAddress = getConfigAs(StationConfig.class).macAddress;
75 logger.debug("Station {}: Initializing station handler for MAC {}", station, macAddress);
77 ProcessorFactory.getProcessor(thing).setChannelGroupId();
78 ProcessorFactory.getProcessor(thing).setNumberOfSensors();
79 } catch (ProcessorNotFoundException e) {
80 logger.warn("Station {}: Unable to set channel group Id and/or number of sensors: {}", station,
82 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, e.getMessage());
85 Thing bridge = getBridge();
87 logger.debug("Station {}: Set station status to match bridge status: {}", station, bridge.getStatus());
88 updateStatus(bridge.getStatus());
93 public void dispose() {
94 macAddress = getConfigAs(StationConfig.class).macAddress;
95 logger.debug("Station {}: Disposing station handler for MAC {}", station, macAddress);
96 updateStatus(ThingStatus.OFFLINE);
100 public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
101 ThingStatus bridgeStatus = bridgeStatusInfo.getStatus();
102 logger.debug("Station {}: Detected bridge status changed to '{}', Update my status", station, bridgeStatus);
103 if (bridgeStatus == ThingStatus.OFFLINE) {
104 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
105 } else if (bridgeStatus == ThingStatus.ONLINE) {
106 updateStatus(ThingStatus.ONLINE);
111 * Handle an update to the station name and location
113 public void handleInfoEvent(String mac, String name, String location) {
114 logger.debug("Station {}: Update name={} and location={} for MAC {}", station, name, location, macAddress);
116 ProcessorFactory.getProcessor(thing).processInfoUpdate(this, station, name, location);
117 } catch (ProcessorNotFoundException e) {
118 logger.debug("Unable to process info event: {}", e.getMessage());
123 * Handle an update to the weather data.
125 public void handleWeatherDataEvent(String jsonData) {
126 logger.debug("Station {}: Processing data event for MAC {}", station, macAddress);
128 ProcessorFactory.getProcessor(thing).processWeatherData(this, station, jsonData);
129 } catch (ProcessorNotFoundException e) {
130 logger.debug("Unable to process weather data event: {}", e.getMessage());
134 public void updateQuantity(String groupId, String channelId, @Nullable Number value, Unit<?> unit) {
135 String channel = groupId + "#" + channelId;
136 if (value != null && isLinked(channel)) {
137 updateState(channel, new QuantityType<>(value, unit));
141 public void updateString(String groupId, String channelId, @Nullable String value) {
142 String channel = groupId + "#" + channelId;
143 if (value != null && isLinked(channel)) {
144 updateState(channel, new StringType(value));
148 public void updateNumber(String groupId, String channelId, @Nullable Number value) {
149 String channel = groupId + "#" + channelId;
150 if (value != null && isLinked(channel)) {
151 if (value instanceof Integer) {
152 updateState(channel, new DecimalType(value.intValue()));
153 } else if (value instanceof Double) {
154 updateState(channel, new DecimalType(value.doubleValue()));
159 public void updateDate(String groupId, String channelId, @Nullable String date) {
160 String channel = groupId + "#" + channelId;
161 if (date != null && isLinked(channel)) {
162 updateState(channel, getLocalDateTimeType(date, getZoneId()));
166 private DateTimeType getLocalDateTimeType(String dateTimeString, ZoneId zoneId) {
167 DateTimeType dateTimeType;
169 Instant instant = Instant.parse(dateTimeString);
170 ZonedDateTime localDateTime = instant.atZone(zoneId);
171 dateTimeType = new DateTimeType(localDateTime);
172 } catch (DateTimeParseException e) {
173 logger.debug("Error parsing date/time string: {}", e.getMessage());
174 dateTimeType = new DateTimeType();
175 } catch (IllegalArgumentException e) {
176 logger.debug("Error converting to DateTimeType: {}", e.getMessage());
177 dateTimeType = new DateTimeType();
182 private ZoneId getZoneId() {
183 return timeZoneProvider.getTimeZone();
187 public void handleCommand(ChannelUID channelUID, Command command) {
188 // Handler doesn't support any commands