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