]> git.basschouten.com Git - openhab-addons.git/blob
bf5ed7c2f2123791b2a4e41b8e4dcfd1e013631b
[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.oceanic.internal.handler;
14
15 import java.math.BigDecimal;
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.concurrent.ScheduledFuture;
20 import java.util.concurrent.TimeUnit;
21
22 import org.eclipse.jdt.annotation.NonNull;
23 import org.openhab.binding.oceanic.internal.OceanicBindingConstants.OceanicChannelSelector;
24 import org.openhab.core.thing.Channel;
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.Type;
34 import org.openhab.core.types.TypeParser;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * The {@link OceanicThingHandler} is the abstract class responsible for handling commands, which are
40  * sent to one of the channels
41  *
42  * @author Karel Goderis - Initial contribution
43  */
44 public abstract class OceanicThingHandler extends BaseThingHandler {
45
46     public static final String INTERVAL = "interval";
47     public static final String BUFFER_SIZE = "buffer";
48     private final Logger logger = LoggerFactory.getLogger(OceanicThingHandler.class);
49
50     protected int bufferSize;
51     protected ScheduledFuture<?> pollingJob;
52     protected static String lastLineReceived = "";
53
54     public OceanicThingHandler(@NonNull Thing thing) {
55         super(thing);
56     }
57
58     private Runnable resetRunnable = () -> {
59         dispose();
60         initialize();
61     };
62
63     private Runnable pollingRunnable = () -> {
64         try {
65             if (getThing().getStatus() == ThingStatus.ONLINE) {
66                 for (Channel aChannel : getThing().getChannels()) {
67                     for (OceanicChannelSelector selector : OceanicChannelSelector.values()) {
68                         ChannelUID theChannelUID = new ChannelUID(getThing().getUID(), selector.toString());
69                         if (aChannel.getUID().equals(theChannelUID)
70                                 && selector.getTypeValue() == OceanicChannelSelector.ValueSelectorType.GET) {
71                             String response = requestResponse(selector.name());
72                             if (response != null && response != "") {
73                                 if (selector.isProperty()) {
74                                     logger.debug("Updating the property '{}' with value '{}'", selector.toString(),
75                                             selector.convertValue(response));
76                                     Map<String, String> properties = editProperties();
77                                     properties.put(selector.toString(), selector.convertValue(response));
78                                     updateProperties(properties);
79                                 } else {
80                                     State value = createStateForType(selector, response);
81                                     updateState(theChannelUID, value);
82                                 }
83                             } else {
84                                 logger.warn("Received an empty answer for '{}'", selector.name());
85                             }
86                         }
87                     }
88                 }
89             }
90         } catch (Exception e) {
91             logger.error("An exception occurred while polling the Oceanic Water Softener: '{}'", e.getMessage(), e);
92             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
93             scheduler.schedule(resetRunnable, 0, TimeUnit.SECONDS);
94         }
95     };
96
97     @Override
98     public void initialize() {
99         if (getConfig().get(BUFFER_SIZE) == null) {
100             bufferSize = 1024;
101         } else {
102             bufferSize = ((BigDecimal) getConfig().get(BUFFER_SIZE)).intValue();
103         }
104
105         if (pollingJob == null || pollingJob.isCancelled()) {
106             pollingJob = scheduler.scheduleWithFixedDelay(pollingRunnable, 1,
107                     ((BigDecimal) getConfig().get(INTERVAL)).intValue(), TimeUnit.SECONDS);
108         }
109     }
110
111     @Override
112     public void dispose() {
113         if (pollingJob != null && !pollingJob.isCancelled()) {
114             pollingJob.cancel(true);
115             pollingJob = null;
116         }
117     }
118
119     @Override
120     public void handleCommand(ChannelUID channelUID, Command command) {
121         if (getThing().getStatus() == ThingStatus.ONLINE) {
122             if (!(command instanceof RefreshType)) {
123                 String commandAsString = command.toString();
124                 String channelID = channelUID.getId();
125
126                 for (Channel aChannel : getThing().getChannels()) {
127                     if (aChannel.getUID().equals(channelUID)) {
128                         try {
129                             OceanicChannelSelector selector = OceanicChannelSelector.getValueSelector(channelID,
130                                     OceanicChannelSelector.ValueSelectorType.SET);
131
132                             switch (selector) {
133                                 case setSV1:
134                                     commandAsString = selector.name() + commandAsString;
135                                     break;
136                                 default:
137                                     commandAsString = selector.name();
138                                     break;
139                             }
140                             String response = requestResponse(commandAsString);
141                             if (response.equals("ERR")) {
142                                 logger.error("An error occurred while setting '{}' to {}", selector.toString(),
143                                         commandAsString);
144                             }
145                         } catch (IllegalArgumentException e) {
146                             logger.warn(
147                                     "An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
148                                     channelID, command.toString());
149                         }
150                         break;
151                     }
152                 }
153             }
154         }
155     }
156
157     @SuppressWarnings("unchecked")
158     private State createStateForType(OceanicChannelSelector selector, String value) {
159         Class<? extends Type> typeClass = selector.getTypeClass();
160         List<Class<? extends State>> stateTypeList = new ArrayList<>();
161
162         stateTypeList.add((Class<? extends State>) typeClass);
163         State state = TypeParser.parseState(stateTypeList, selector.convertValue(value));
164
165         return state;
166     }
167
168     protected abstract String requestResponse(String commandAsString);
169 }