]> git.basschouten.com Git - openhab-addons.git/blob
8ccbe584c822cf88b1eff5b8093e14afbdd285f7
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.neato.internal.handler;
14
15 import static org.openhab.binding.neato.internal.NeatoBindingConstants.*;
16
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
19
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.openhab.binding.neato.internal.CouldNotFindRobotException;
22 import org.openhab.binding.neato.internal.NeatoBindingConstants;
23 import org.openhab.binding.neato.internal.NeatoCommunicationException;
24 import org.openhab.binding.neato.internal.NeatoRobot;
25 import org.openhab.binding.neato.internal.classes.Cleaning;
26 import org.openhab.binding.neato.internal.classes.Details;
27 import org.openhab.binding.neato.internal.classes.NeatoState;
28 import org.openhab.binding.neato.internal.config.NeatoRobotConfig;
29 import org.openhab.core.library.types.DecimalType;
30 import org.openhab.core.library.types.OnOffType;
31 import org.openhab.core.library.types.StringType;
32 import org.openhab.core.thing.ChannelUID;
33 import org.openhab.core.thing.Thing;
34 import org.openhab.core.thing.ThingStatus;
35 import org.openhab.core.thing.ThingStatusDetail;
36 import org.openhab.core.thing.binding.BaseThingHandler;
37 import org.openhab.core.types.Command;
38 import org.openhab.core.types.RefreshType;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * The {@link NeatoHandler} is responsible for handling commands, which are
44  * sent to one of the channels.
45  *
46  * @author Patrik Wimnell - Initial contribution
47  * @author Jeff Lauterbach - Code Cleanup and Refactor
48  */
49 public class NeatoHandler extends BaseThingHandler {
50
51     private Logger logger = LoggerFactory.getLogger(NeatoHandler.class);
52
53     private NeatoRobot mrRobot;
54
55     private int refreshTime;
56     private ScheduledFuture<?> refreshTask;
57
58     public NeatoHandler(Thing thing) {
59         super(thing);
60     }
61
62     @Override
63     public void handleCommand(@NonNull ChannelUID channelUID, Command command) {
64         if (command instanceof RefreshType) {
65             refreshStateAndUpdate();
66         } else if (channelUID.getId().equals(NeatoBindingConstants.COMMAND)) {
67             sendCommandToRobot(command);
68         }
69     }
70
71     private void sendCommandToRobot(Command command) {
72         logger.debug("Ok - will handle command for CHANNEL_COMMAND");
73
74         try {
75             mrRobot.sendCommand(command.toString());
76         } catch (NeatoCommunicationException e) {
77             logger.debug("Error while processing command from openHAB.", e);
78             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
79         }
80         this.refreshStateAndUpdate();
81     }
82
83     @Override
84     public void dispose() {
85         logger.debug("Running dispose()");
86         if (this.refreshTask != null) {
87             this.refreshTask.cancel(true);
88             this.refreshTask = null;
89         }
90     }
91
92     @Override
93     public void initialize() {
94         updateStatus(ThingStatus.UNKNOWN);
95         logger.debug("Will boot up Neato Vacuum Cleaner binding!");
96
97         NeatoRobotConfig config = getThing().getConfiguration().as(NeatoRobotConfig.class);
98
99         logger.debug("Neato Robot Config: {}", config);
100
101         refreshTime = config.getRefresh();
102         if (refreshTime < 30) {
103             logger.warn(
104                     "Refresh time [{}] is not valid. Refresh time must be at least 30 seconds.  Setting to minimum of 30 sec",
105                     refreshTime);
106             config.setRefresh(30);
107         }
108
109         mrRobot = new NeatoRobot(config);
110         startAutomaticRefresh();
111     }
112
113     public void refreshStateAndUpdate() {
114         if (mrRobot != null) {
115             try {
116                 mrRobot.sendGetState();
117                 updateStatus(ThingStatus.ONLINE);
118
119                 mrRobot.sendGetGeneralInfo();
120
121                 publishChannels();
122             } catch (NeatoCommunicationException | CouldNotFindRobotException e) {
123                 logger.debug("Error when refreshing state.", e);
124                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
125             }
126         }
127     }
128
129     private void startAutomaticRefresh() {
130         Runnable refresher = () -> refreshStateAndUpdate();
131
132         this.refreshTask = scheduler.scheduleWithFixedDelay(refresher, 0, refreshTime, TimeUnit.SECONDS);
133         logger.debug("Start automatic refresh at {} seconds", refreshTime);
134     }
135
136     private void publishChannels() {
137         logger.debug("Updating Channels");
138
139         NeatoState neatoState = mrRobot.getState();
140         if (neatoState == null) {
141             return;
142         }
143
144         updateProperty(Thing.PROPERTY_FIRMWARE_VERSION, neatoState.getMeta().getFirmware());
145         updateProperty(Thing.PROPERTY_MODEL_ID, neatoState.getMeta().getModelName());
146
147         updateState(CHANNEL_STATE, new StringType(neatoState.getRobotState().name()));
148
149         String error = neatoState.getError() != null ? neatoState.getError() : "";
150         updateState(CHANNEL_ERROR, new StringType(error));
151         updateState(CHANNEL_ACTION, new StringType(neatoState.getRobotAction().name()));
152
153         Details details = neatoState.getDetails();
154         if (details != null) {
155             updateState(CHANNEL_BATTERY, new DecimalType(details.getCharge()));
156             updateState(CHANNEL_DOCKHASBEENSEEN, OnOffType.from(details.getDockHasBeenSeen()));
157             updateState(CHANNEL_ISCHARGING, OnOffType.from(details.getIsCharging()));
158             updateState(CHANNEL_ISSCHEDULED, OnOffType.from(details.getIsScheduleEnabled()));
159             updateState(CHANNEL_ISDOCKED, OnOffType.from(details.getIsDocked()));
160         }
161
162         Cleaning cleaning = neatoState.getCleaning();
163         if (cleaning != null) {
164             updateState(CHANNEL_CLEANINGCATEGORY, new StringType(cleaning.getCategory().name()));
165             updateState(CHANNEL_CLEANINGMODE, new StringType(cleaning.getMode().name()));
166             updateState(CHANNEL_CLEANINGMODIFIER, new StringType(cleaning.getModifier().name()));
167             updateState(CHANNEL_CLEANINGSPOTWIDTH, new DecimalType(cleaning.getSpotWidth()));
168             updateState(CHANNEL_CLEANINGSPOTHEIGHT, new DecimalType(cleaning.getSpotHeight()));
169         }
170     }
171 }