]> git.basschouten.com Git - openhab-addons.git/blob
edddaeb764fe85c4690e2bf1633dc0360ada41cf
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.danfossairunit.internal;
14
15 import static org.openhab.binding.danfossairunit.internal.DanfossAirUnitBindingConstants.*;
16
17 import java.io.IOException;
18 import java.net.InetAddress;
19 import java.net.UnknownHostException;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.core.thing.ChannelUID;
26 import org.openhab.core.thing.Thing;
27 import org.openhab.core.thing.ThingStatus;
28 import org.openhab.core.thing.ThingStatusDetail;
29 import org.openhab.core.thing.binding.BaseThingHandler;
30 import org.openhab.core.types.Command;
31 import org.openhab.core.types.RefreshType;
32 import org.openhab.core.types.State;
33 import org.openhab.core.types.UnDefType;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * The {@link DanfossAirUnitHandler} is responsible for handling commands, which are
39  * sent to one of the channels.
40  *
41  * @author Ralf Duckstein - Initial contribution
42  * @author Robert Bach - heavy refactorings
43  */
44 @NonNullByDefault
45 public class DanfossAirUnitHandler extends BaseThingHandler {
46
47     private final Logger logger = LoggerFactory.getLogger(DanfossAirUnitHandler.class);
48     private @NonNullByDefault({}) DanfossAirUnitConfiguration config;
49     private @Nullable ValueCache valueCache;
50     private @Nullable ScheduledFuture<?> pollingJob;
51     private @Nullable DanfossAirUnit hrv;
52
53     public DanfossAirUnitHandler(Thing thing) {
54         super(thing);
55     }
56
57     @Override
58     public void handleCommand(ChannelUID channelUID, Command command) {
59         if (command instanceof RefreshType) {
60             updateAllChannels();
61         } else {
62             try {
63                 DanfossAirUnit danfossAirUnit = hrv;
64                 if (danfossAirUnit != null) {
65                     Channel channel = Channel.getByName(channelUID.getIdWithoutGroup());
66                     DanfossAirUnitWriteAccessor writeAccessor = channel.getWriteAccessor();
67                     if (writeAccessor != null) {
68                         updateState(channelUID, writeAccessor.access(danfossAirUnit, command));
69                     }
70                 } else {
71                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.NONE,
72                             "Air unit connection not initialized.");
73                     return;
74                 }
75             } catch (IllegalArgumentException e) {
76                 logger.debug("Ignoring unknown channel id: {}", channelUID.getIdWithoutGroup(), e);
77             } catch (IOException ioe) {
78                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, ioe.getMessage());
79             }
80         }
81     }
82
83     @Override
84     public void initialize() {
85         updateStatus(ThingStatus.UNKNOWN);
86         config = getConfigAs(DanfossAirUnitConfiguration.class);
87         valueCache = new ValueCache(config.updateUnchangedValuesEveryMillis);
88         try {
89             hrv = new DanfossAirUnit(InetAddress.getByName(config.host), 30046);
90             DanfossAirUnit danfossAirUnit = hrv;
91             scheduler.execute(() -> {
92                 try {
93                     thing.setProperty(PROPERTY_UNIT_NAME, danfossAirUnit.getUnitName());
94                     thing.setProperty(PROPERTY_SERIAL, danfossAirUnit.getUnitSerialNumber());
95                     pollingJob = scheduler.scheduleWithFixedDelay(this::updateAllChannels, 5, config.refreshInterval,
96                             TimeUnit.SECONDS);
97                     updateStatus(ThingStatus.ONLINE);
98                 } catch (IOException e) {
99                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
100                 }
101             });
102         } catch (UnknownHostException e) {
103             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
104                     "Unknown host: " + config.host);
105             return;
106         }
107     }
108
109     private void updateAllChannels() {
110         DanfossAirUnit danfossAirUnit = hrv;
111         if (danfossAirUnit != null) {
112             logger.debug("Updating DanfossHRV data '{}'", getThing().getUID());
113
114             for (Channel channel : Channel.values()) {
115                 if (Thread.interrupted()) {
116                     logger.debug("Polling thread interrupted...");
117                     return;
118                 }
119                 try {
120                     updateState(channel.getGroup().getGroupName(), channel.getChannelName(),
121                             channel.getReadAccessor().access(danfossAirUnit));
122                 } catch (UnexpectedResponseValueException e) {
123                     updateState(channel.getGroup().getGroupName(), channel.getChannelName(), UnDefType.UNDEF);
124                     logger.debug(
125                             "Cannot update channel {}: an unexpected or invalid response has been received from the air unit: {}",
126                             channel.getChannelName(), e.getMessage());
127                 } catch (IOException e) {
128                     updateState(channel.getGroup().getGroupName(), channel.getChannelName(), UnDefType.UNDEF);
129                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
130                     logger.debug("Cannot update channel {}: an error occurred retrieving the value: {}",
131                             channel.getChannelName(), e.getMessage());
132                 }
133             }
134
135             if (getThing().getStatus() == ThingStatus.OFFLINE) {
136                 updateStatus(ThingStatus.ONLINE);
137             }
138         }
139     }
140
141     @Override
142     public void dispose() {
143         logger.debug("Disposing Danfoss HRV handler '{}'", getThing().getUID());
144
145         if (pollingJob != null) {
146             pollingJob.cancel(true);
147             pollingJob = null;
148         }
149
150         if (hrv != null) {
151             hrv.cleanUp();
152             hrv = null;
153         }
154     }
155
156     private void updateState(String groupId, String channelId, State state) {
157         if (valueCache.updateValue(channelId, state)) {
158             updateState(new ChannelUID(thing.getUID(), groupId, channelId), state);
159         }
160     }
161 }