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.neato.internal.handler;
15 import static org.openhab.binding.neato.internal.NeatoBindingConstants.*;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
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;
43 * The {@link NeatoHandler} is responsible for handling commands, which are
44 * sent to one of the channels.
46 * @author Patrik Wimnell - Initial contribution
47 * @author Jeff Lauterbach - Code Cleanup and Refactor
49 public class NeatoHandler extends BaseThingHandler {
51 private Logger logger = LoggerFactory.getLogger(NeatoHandler.class);
53 private NeatoRobot mrRobot;
55 private int refreshTime;
56 private ScheduledFuture<?> refreshTask;
58 public NeatoHandler(Thing thing) {
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);
71 private void sendCommandToRobot(Command command) {
72 logger.debug("Ok - will handle command for CHANNEL_COMMAND");
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());
80 this.refreshStateAndUpdate();
84 public void dispose() {
85 logger.debug("Running dispose()");
86 if (this.refreshTask != null) {
87 this.refreshTask.cancel(true);
88 this.refreshTask = null;
93 public void initialize() {
94 updateStatus(ThingStatus.UNKNOWN);
95 logger.debug("Will boot up Neato Vacuum Cleaner binding!");
97 NeatoRobotConfig config = getThing().getConfiguration().as(NeatoRobotConfig.class);
99 logger.debug("Neato Robot Config: {}", config);
101 refreshTime = config.getRefresh();
102 if (refreshTime < 30) {
104 "Refresh time [{}] is not valid. Refresh time must be at least 30 seconds. Setting to minimum of 30 sec",
106 config.setRefresh(30);
109 mrRobot = new NeatoRobot(config);
110 startAutomaticRefresh();
113 public void refreshStateAndUpdate() {
114 if (mrRobot != null) {
116 mrRobot.sendGetState();
117 updateStatus(ThingStatus.ONLINE);
119 mrRobot.sendGetGeneralInfo();
122 } catch (NeatoCommunicationException | CouldNotFindRobotException e) {
123 logger.debug("Error when refreshing state.", e);
124 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
129 private void startAutomaticRefresh() {
130 Runnable refresher = () -> refreshStateAndUpdate();
132 this.refreshTask = scheduler.scheduleWithFixedDelay(refresher, 0, refreshTime, TimeUnit.SECONDS);
133 logger.debug("Start automatic refresh at {} seconds", refreshTime);
136 private void publishChannels() {
137 logger.debug("Updating Channels");
139 NeatoState neatoState = mrRobot.getState();
140 if (neatoState == null) {
144 updateProperty(Thing.PROPERTY_FIRMWARE_VERSION, neatoState.getMeta().getFirmware());
145 updateProperty(Thing.PROPERTY_MODEL_ID, neatoState.getMeta().getModelName());
147 updateState(CHANNEL_STATE, new StringType(neatoState.getRobotState().name()));
149 String error = neatoState.getError() != null ? neatoState.getError() : "";
150 updateState(CHANNEL_ERROR, new StringType(error));
151 updateState(CHANNEL_ACTION, new StringType(neatoState.getRobotAction().name()));
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()));
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()));