added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.automower-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-automower" description="Automower Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.automower/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link AutomowerBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AutomowerBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = "automower";
|
||||
|
||||
public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge");
|
||||
|
||||
// generic thing types
|
||||
public static final ThingTypeUID THING_TYPE_AUTOMOWER = new ThingTypeUID(BINDING_ID, "automower");
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_MOWER_NAME = "name";
|
||||
public static final String CHANNEL_STATUS_MODE = "mode";
|
||||
public static final String CHANNEL_STATUS_ACTIVITY = "activity";
|
||||
public static final String CHANNEL_STATUS_STATE = "state";
|
||||
public static final String CHANNEL_STATUS_LAST_UPDATE = "last-update";
|
||||
public static final String CHANNEL_STATUS_BATTERY = "battery";
|
||||
public static final String CHANNEL_STATUS_ERROR_CODE = "error-code";
|
||||
public static final String CHANNEL_STATUS_ERROR_TIMESTAMP = "error-timestamp";
|
||||
|
||||
// Automower properties
|
||||
public static final String AUTOMOWER_ID = "mowerId";
|
||||
public static final String AUTOMOWER_NAME = "mowerName";
|
||||
public static final String AUTOMOWER_MODEL = "mowerModel";
|
||||
public static final String AUTOMOWER_SERIAL_NUMBER = "mowerSerialNumber";
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.automower.internal.bridge.AutomowerBridgeHandler;
|
||||
import org.openhab.binding.automower.internal.discovery.AutomowerDiscoveryService;
|
||||
import org.openhab.binding.automower.internal.things.AutomowerHandler;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link AutomowerHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.automower", service = ThingHandlerFactory.class)
|
||||
public class AutomowerHandlerFactory extends BaseThingHandlerFactory {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.unmodifiableSet(Stream
|
||||
.of(AutomowerBridgeHandler.SUPPORTED_THING_TYPES.stream(), AutomowerHandler.SUPPORTED_THING_TYPES.stream())
|
||||
.flatMap(Function.identity()).collect(Collectors.toSet()));
|
||||
|
||||
private final OAuthFactory oAuthFactory;
|
||||
protected final @NonNullByDefault({}) HttpClient httpClient;
|
||||
private @Nullable ServiceRegistration<?> automowerDiscoveryServiceRegistration;
|
||||
|
||||
@Activate
|
||||
public AutomowerHandlerFactory(@Reference OAuthFactory oAuthFactory,
|
||||
@Reference HttpClientFactory httpClientFactory) {
|
||||
this.oAuthFactory = oAuthFactory;
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
if (AutomowerBridgeHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||
AutomowerBridgeHandler handler = new AutomowerBridgeHandler((Bridge) thing, oAuthFactory, httpClient);
|
||||
registerAutomowerDiscoveryService(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
if (AutomowerHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||
return new AutomowerHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void removeHandler(ThingHandler thingHandler) {
|
||||
if (thingHandler instanceof AutomowerBridgeHandler) {
|
||||
if (automowerDiscoveryServiceRegistration != null) {
|
||||
// remove discovery service, if bridge handler is removed
|
||||
automowerDiscoveryServiceRegistration.unregister();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerAutomowerDiscoveryService(AutomowerBridgeHandler handler) {
|
||||
AutomowerDiscoveryService discoveryService = new AutomowerDiscoveryService(handler);
|
||||
this.automowerDiscoveryServiceRegistration = bundleContext.registerService(DiscoveryService.class.getName(),
|
||||
discoveryService, new Hashtable<>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.actions;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.automower.internal.things.AutomowerCommand;
|
||||
import org.openhab.binding.automower.internal.things.AutomowerHandler;
|
||||
import org.openhab.core.automation.annotation.ActionInput;
|
||||
import org.openhab.core.automation.annotation.RuleAction;
|
||||
import org.openhab.core.thing.binding.ThingActions;
|
||||
import org.openhab.core.thing.binding.ThingActionsScope;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@ThingActionsScope(name = "automower")
|
||||
@NonNullByDefault
|
||||
public class AutomowerActions implements ThingActions, IAutomowerActions {
|
||||
private final Logger logger = LoggerFactory.getLogger(AutomowerActions.class);
|
||||
private @Nullable AutomowerHandler handler;
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
this.handler = (AutomowerHandler) handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AutomowerHandler getThingHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/action-start-label", description = "@text/action-start-desc")
|
||||
public void start(
|
||||
@ActionInput(name = "duration", label = "@text/action-input-duration-label", description = "@text/action-input-duration-desc") int durationMin) {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
if (automowerHandler == null) {
|
||||
logger.warn("Automower Action service ThingHandler is null!");
|
||||
} else {
|
||||
automowerHandler.sendAutomowerCommand(AutomowerCommand.START, durationMin);
|
||||
}
|
||||
}
|
||||
|
||||
public static void start(@Nullable ThingActions actions, int durationMin) {
|
||||
invokeMethodOf(actions).start(durationMin);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/action-pause-label", description = "@text/action-pause-desc")
|
||||
public void pause() {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
if (automowerHandler == null) {
|
||||
logger.warn("Automower Action service ThingHandler is null!");
|
||||
} else {
|
||||
automowerHandler.sendAutomowerCommand(AutomowerCommand.PAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void pause(@Nullable ThingActions actions) {
|
||||
invokeMethodOf(actions).pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/action-parkuntilnextschedule-label", description = "@text/action-parkuntilnextschedule-desc")
|
||||
public void parkUntilNextSchedule() {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
if (automowerHandler == null) {
|
||||
logger.warn("Automower Action service ThingHandler is null!");
|
||||
} else {
|
||||
automowerHandler.sendAutomowerCommand(AutomowerCommand.PARK_UNTIL_NEXT_SCHEDULE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void parkUntilNextSchedule(@Nullable ThingActions actions) {
|
||||
invokeMethodOf(actions).parkUntilNextSchedule();
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/action-parkuntilfurthernotice-label", description = "@text/action-parkuntilfurthernotice-desc")
|
||||
public void parkUntilFurtherNotice() {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
if (automowerHandler == null) {
|
||||
logger.warn("Automower Action service ThingHandler is null!");
|
||||
} else {
|
||||
automowerHandler.sendAutomowerCommand(AutomowerCommand.PARK_UNTIL_FURTHER_NOTICE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void parkUntilFurtherNotice(@Nullable ThingActions actions) {
|
||||
invokeMethodOf(actions).parkUntilFurtherNotice();
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/action-park-label", description = "@text/action-park-desc")
|
||||
public void park(
|
||||
@ActionInput(name = "duration", label = "@text/action-input-duration-label", description = "@text/action-input-duration-desc") int durationMin) {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
if (automowerHandler == null) {
|
||||
logger.warn("Automower Action service ThingHandler is null!");
|
||||
} else {
|
||||
automowerHandler.sendAutomowerCommand(AutomowerCommand.PARK, durationMin);
|
||||
}
|
||||
}
|
||||
|
||||
public static void park(@Nullable ThingActions actions, int durationMin) {
|
||||
invokeMethodOf(actions).park(durationMin);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/action-resumeschedule-label", description = "@text/action-resumeschedule-desc")
|
||||
public void resumeSchedule() {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
if (automowerHandler == null) {
|
||||
logger.warn("Automower Action service ThingHandler is null!");
|
||||
} else {
|
||||
automowerHandler.sendAutomowerCommand(AutomowerCommand.RESUME_SCHEDULE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void resumeSchedule(@Nullable ThingActions actions) {
|
||||
invokeMethodOf(actions).resumeSchedule();
|
||||
}
|
||||
|
||||
private static IAutomowerActions invokeMethodOf(@Nullable ThingActions actions) {
|
||||
if (actions == null) {
|
||||
throw new IllegalArgumentException("actions cannot be null");
|
||||
}
|
||||
if (actions.getClass().getName().equals(AutomowerActions.class.getName())) {
|
||||
if (actions instanceof AutomowerActions) {
|
||||
return (IAutomowerActions) actions;
|
||||
} else {
|
||||
return (IAutomowerActions) Proxy.newProxyInstance(IAutomowerActions.class.getClassLoader(),
|
||||
new Class[] { IAutomowerActions.class }, (Object proxy, Method method, Object[] args) -> {
|
||||
Method m = actions.getClass().getDeclaredMethod(method.getName(),
|
||||
method.getParameterTypes());
|
||||
return m.invoke(actions, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Actions is not an instance of IAutomowerActions");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.actions;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Actions that can be executed for an automower
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface IAutomowerActions {
|
||||
|
||||
void resumeSchedule();
|
||||
|
||||
void park(int durationMin);
|
||||
|
||||
void parkUntilFurtherNotice();
|
||||
|
||||
void parkUntilNextSchedule();
|
||||
|
||||
void pause();
|
||||
|
||||
void start(int durationMin);
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.bridge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.AutomowerConnectApi;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.Mower;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerCommand;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerCommandAttributes;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerCommandRequest;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerListResult;
|
||||
import org.openhab.binding.automower.internal.rest.exceptions.AutomowerCommunicationException;
|
||||
import org.openhab.binding.automower.internal.things.AutomowerCommand;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthClientService;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthException;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthResponseException;
|
||||
|
||||
/**
|
||||
* The {@link AutomowerBridge} allows the communication to the various Husqvarna rest apis like the
|
||||
* AutomowerConnectApi or the AuthenticationApi
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AutomowerBridge {
|
||||
|
||||
private final OAuthClientService authService;
|
||||
private final String appKey;
|
||||
private final String userName;
|
||||
private final String password;
|
||||
|
||||
private final AutomowerConnectApi automowerApi;
|
||||
|
||||
public AutomowerBridge(OAuthClientService authService, String appKey, String userName, String password,
|
||||
HttpClient httpClient, ScheduledExecutorService scheduler) {
|
||||
this.authService = authService;
|
||||
this.appKey = appKey;
|
||||
this.userName = userName;
|
||||
this.password = password;
|
||||
|
||||
this.automowerApi = new AutomowerConnectApi(httpClient);
|
||||
}
|
||||
|
||||
private AccessTokenResponse authenticate() throws AutomowerCommunicationException {
|
||||
try {
|
||||
AccessTokenResponse result = authService.getAccessTokenResponse();
|
||||
if (result == null) {
|
||||
result = authService.getAccessTokenByResourceOwnerPasswordCredentials(userName, password, null);
|
||||
}
|
||||
return result;
|
||||
} catch (OAuthException | IOException | OAuthResponseException e) {
|
||||
throw new AutomowerCommunicationException("Unable to authenticate", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A result containing a list of mowers that are available for the current user
|
||||
* @throws AutomowerCommunicationException In case the query cannot be executed successfully
|
||||
*/
|
||||
public MowerListResult getAutomowers() throws AutomowerCommunicationException {
|
||||
return automowerApi.getMowers(appKey, authenticate().getAccessToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id The id of the mower to query
|
||||
* @return A detailed status of the mower with the specified id
|
||||
* @throws AutomowerCommunicationException In case the query cannot be executed successfully
|
||||
*/
|
||||
public Mower getAutomowerStatus(String id) throws AutomowerCommunicationException {
|
||||
return automowerApi.getMower(appKey, authenticate().getAccessToken(), id).getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command to the automower with the specified id
|
||||
*
|
||||
* @param id The id of the mower
|
||||
* @param command The command that should be sent. Valid values are: "Start", "ResumeSchedule", "Pause", "Park",
|
||||
* "ParkUntilNextSchedule", "ParkUntilFurtherNotice"
|
||||
* @param commandDuration The duration of the command. This is only evaluated for "Start" and "Park" commands
|
||||
* @throws AutomowerCommunicationException In case the query cannot be executed successfully
|
||||
*/
|
||||
public void sendAutomowerCommand(String id, AutomowerCommand command, long commandDuration)
|
||||
throws AutomowerCommunicationException {
|
||||
|
||||
MowerCommandAttributes attributes = new MowerCommandAttributes();
|
||||
attributes.setDuration(commandDuration);
|
||||
|
||||
MowerCommand mowerCommand = new MowerCommand();
|
||||
mowerCommand.setType(command.getCommand());
|
||||
mowerCommand.setAttributes(attributes);
|
||||
|
||||
MowerCommandRequest request = new MowerCommandRequest();
|
||||
request.setData(mowerCommand);
|
||||
automowerApi.sendCommand(appKey, authenticate().getAccessToken(), id, request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.bridge;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link AutomowerBridgeConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public final class AutomowerBridgeConfiguration {
|
||||
private @Nullable String appKey;
|
||||
private @Nullable String userName;
|
||||
private @Nullable String password;
|
||||
|
||||
private @Nullable Integer pollingInterval;
|
||||
|
||||
/**
|
||||
* @return The polling interval for the automower state in s
|
||||
*/
|
||||
public @Nullable Integer getPollingInterval() {
|
||||
return pollingInterval;
|
||||
}
|
||||
|
||||
public void setPollingInterval(Integer pollingInterval) {
|
||||
this.pollingInterval = pollingInterval;
|
||||
}
|
||||
|
||||
public @Nullable String getAppKey() {
|
||||
return appKey;
|
||||
}
|
||||
|
||||
public void setAppKey(String appKey) {
|
||||
this.appKey = appKey;
|
||||
}
|
||||
|
||||
public @Nullable String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public @Nullable String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.bridge;
|
||||
|
||||
import static org.openhab.binding.automower.internal.AutomowerBindingConstants.THING_TYPE_BRIDGE;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerListResult;
|
||||
import org.openhab.binding.automower.internal.rest.exceptions.AutomowerCommunicationException;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthClientService;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link AutomowerBridgeHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AutomowerBridgeHandler extends BaseBridgeHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(AutomowerBridgeHandler.class);
|
||||
|
||||
private static final String HUSQVARNA_API_TOKEN_URL = "https://api.authentication.husqvarnagroup.dev/v1/oauth2/token";
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE);
|
||||
private static final long DEFAULT_POLLING_INTERVAL_S = TimeUnit.HOURS.toSeconds(1);
|
||||
|
||||
private final OAuthFactory oAuthFactory;
|
||||
|
||||
private @NonNullByDefault({}) OAuthClientService oAuthService;
|
||||
private @Nullable ScheduledFuture<?> automowerBridgePollingJob;
|
||||
private @Nullable AutomowerBridge bridge;
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public AutomowerBridgeHandler(Bridge bridge, OAuthFactory oAuthFactory, HttpClient httpClient) {
|
||||
super(bridge);
|
||||
this.oAuthFactory = oAuthFactory;
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
private void pollAutomowers(AutomowerBridge bridge) {
|
||||
MowerListResult automowers;
|
||||
try {
|
||||
automowers = bridge.getAutomowers();
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
logger.debug("Found {} automowers", automowers.getData().size());
|
||||
} catch (AutomowerCommunicationException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/comm-error-query-mowers-failed");
|
||||
logger.warn("Unable to fetch automowers: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
AutomowerBridge currentBridge = bridge;
|
||||
if (currentBridge != null) {
|
||||
stopAutomowerBridgePolling(currentBridge);
|
||||
bridge = null;
|
||||
}
|
||||
oAuthFactory.ungetOAuthService(thing.getUID().getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
AutomowerBridgeConfiguration bridgeConfiguration = getConfigAs(AutomowerBridgeConfiguration.class);
|
||||
|
||||
final String appKey = bridgeConfiguration.getAppKey();
|
||||
final String userName = bridgeConfiguration.getUserName();
|
||||
final String password = bridgeConfiguration.getPassword();
|
||||
final Integer pollingIntervalS = bridgeConfiguration.getPollingInterval();
|
||||
|
||||
if (appKey == null || appKey.isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/conf-error-no-app-key");
|
||||
} else if (userName == null || userName.isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/conf-error-no-username");
|
||||
} else if (password == null || password.isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/conf-error-no-password");
|
||||
} else if (pollingIntervalS != null && pollingIntervalS < 1) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/conf-error-invalid-polling-interval");
|
||||
} else {
|
||||
oAuthService = oAuthFactory.createOAuthClientService(thing.getUID().getAsString(), HUSQVARNA_API_TOKEN_URL,
|
||||
null, appKey, null, null, null);
|
||||
|
||||
if (bridge == null) {
|
||||
AutomowerBridge currentBridge = new AutomowerBridge(oAuthService, appKey, userName, password,
|
||||
httpClient, scheduler);
|
||||
bridge = currentBridge;
|
||||
startAutomowerBridgePolling(currentBridge, pollingIntervalS);
|
||||
}
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAutomowerBridgePolling(AutomowerBridge bridge, @Nullable Integer pollingIntervalS) {
|
||||
ScheduledFuture<?> currentPollingJob = automowerBridgePollingJob;
|
||||
if (currentPollingJob == null) {
|
||||
final long pollingIntervalToUse = pollingIntervalS == null ? DEFAULT_POLLING_INTERVAL_S : pollingIntervalS;
|
||||
automowerBridgePollingJob = scheduler.scheduleWithFixedDelay(() -> pollAutomowers(bridge), 1,
|
||||
pollingIntervalToUse, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopAutomowerBridgePolling(AutomowerBridge bridge) {
|
||||
ScheduledFuture<?> currentPollingJob = automowerBridgePollingJob;
|
||||
if (currentPollingJob != null) {
|
||||
currentPollingJob.cancel(true);
|
||||
automowerBridgePollingJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
public @Nullable AutomowerBridge getAutomowerBridge() {
|
||||
return bridge;
|
||||
}
|
||||
|
||||
public Optional<MowerListResult> getAutomowers() {
|
||||
AutomowerBridge currentBridge = bridge;
|
||||
if (currentBridge == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try {
|
||||
return Optional.of(currentBridge.getAutomowers());
|
||||
} catch (AutomowerCommunicationException e) {
|
||||
logger.debug("Bridge cannot get list of available automowers {}", e.getMessage());
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.automower.internal.AutomowerBindingConstants.THING_TYPE_AUTOMOWER;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.automower.internal.AutomowerBindingConstants;
|
||||
import org.openhab.binding.automower.internal.bridge.AutomowerBridgeHandler;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.Mower;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerListResult;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
|
||||
/**
|
||||
* The {@link AutomowerDiscoveryService} is responsible for discovering new mowers available for the
|
||||
* configured app key.
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AutomowerDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
private final AutomowerBridgeHandler bridgeHandler;
|
||||
|
||||
public AutomowerDiscoveryService(AutomowerBridgeHandler bridgeHandler) {
|
||||
super(Collections.singleton(THING_TYPE_AUTOMOWER), 10, false);
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
Optional<MowerListResult> registeredMowers = bridgeHandler.getAutomowers();
|
||||
|
||||
registeredMowers.ifPresent(mowers -> {
|
||||
for (Mower mower : mowers.getData()) {
|
||||
ThingUID bridgeUID = bridgeHandler.getThing().getUID();
|
||||
ThingTypeUID thingTypeUID = THING_TYPE_AUTOMOWER;
|
||||
ThingUID mowerThingUid = new ThingUID(THING_TYPE_AUTOMOWER, bridgeUID, mower.getId());
|
||||
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(AutomowerBindingConstants.AUTOMOWER_ID, mower.getId());
|
||||
properties.put(AutomowerBindingConstants.AUTOMOWER_SERIAL_NUMBER,
|
||||
mower.getAttributes().getSystem().getSerialNumber());
|
||||
properties.put(AutomowerBindingConstants.AUTOMOWER_MODEL, mower.getAttributes().getSystem().getModel());
|
||||
properties.put(AutomowerBindingConstants.AUTOMOWER_NAME, mower.getAttributes().getSystem().getName());
|
||||
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(mowerThingUid)
|
||||
.withThingType(thingTypeUID).withProperties(properties).withBridge(bridgeUID)
|
||||
.withRepresentationProperty(AutomowerBindingConstants.AUTOMOWER_ID)
|
||||
.withLabel(mower.getAttributes().getSystem().getName() + " (Automower "
|
||||
+ mower.getAttributes().getSystem().getModel() + ")")
|
||||
.build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
/**
|
||||
* Base class for the Husqvarna apis
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class HusqvarnaApi {
|
||||
|
||||
private final HttpClient httpClient;
|
||||
protected final Gson gson;
|
||||
|
||||
protected HusqvarnaApi(HttpClient httpClient) {
|
||||
this.httpClient = httpClient;
|
||||
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
gson = gsonBuilder.create();
|
||||
}
|
||||
|
||||
protected abstract String getBaseUrl();
|
||||
|
||||
protected HttpClient getHttpClient() {
|
||||
return httpClient;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.openhab.binding.automower.internal.rest.api.HusqvarnaApi;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerCommandRequest;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerListResult;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerResult;
|
||||
import org.openhab.binding.automower.internal.rest.exceptions.AutomowerCommunicationException;
|
||||
import org.openhab.binding.automower.internal.rest.exceptions.UnauthorizedException;
|
||||
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* Allows access to the AutomowerConnectApi
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AutomowerConnectApi extends HusqvarnaApi {
|
||||
|
||||
public AutomowerConnectApi(HttpClient httpClient) {
|
||||
super(httpClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBaseUrl() {
|
||||
return "https://api.amc.husqvarna.dev/v1";
|
||||
}
|
||||
|
||||
public MowerListResult getMowers(String appKey, String token) throws AutomowerCommunicationException {
|
||||
final Request request = getHttpClient().newRequest(getBaseUrl() + "/mowers");
|
||||
request.method(HttpMethod.GET);
|
||||
|
||||
ContentResponse response = executeRequest(appKey, token, request);
|
||||
|
||||
return parseResponse(response, MowerListResult.class);
|
||||
}
|
||||
|
||||
public MowerResult getMower(String appKey, String token, String mowerId) throws AutomowerCommunicationException {
|
||||
final Request request = getHttpClient().newRequest(getBaseUrl() + "/mowers/" + mowerId);
|
||||
request.method(HttpMethod.GET);
|
||||
|
||||
ContentResponse response = executeRequest(appKey, token, request);
|
||||
|
||||
return parseResponse(response, MowerResult.class);
|
||||
}
|
||||
|
||||
public void sendCommand(String appKey, String token, String id, MowerCommandRequest command)
|
||||
throws AutomowerCommunicationException {
|
||||
final Request request = getHttpClient().newRequest(getBaseUrl() + "/mowers/" + id + "/actions");
|
||||
request.method(HttpMethod.POST);
|
||||
|
||||
request.content(new StringContentProvider(gson.toJson(command)));
|
||||
|
||||
ContentResponse response = executeRequest(appKey, token, request);
|
||||
|
||||
checkForError(response, response.getStatus());
|
||||
}
|
||||
|
||||
private ContentResponse executeRequest(String appKey, String token, final Request request)
|
||||
throws AutomowerCommunicationException {
|
||||
|
||||
request.timeout(10, TimeUnit.SECONDS);
|
||||
|
||||
request.header("Authorization-Provider", "husqvarna");
|
||||
request.header("Authorization", "Bearer " + token);
|
||||
request.header("X-Api-Key", appKey);
|
||||
request.header("Content-Type", "application/vnd.api+json");
|
||||
|
||||
ContentResponse response;
|
||||
try {
|
||||
response = request.send();
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||
throw new AutomowerCommunicationException(e);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private <T> T parseResponse(ContentResponse response, Class<T> type) throws AutomowerCommunicationException {
|
||||
int statusCode = response.getStatus();
|
||||
|
||||
checkForError(response, statusCode);
|
||||
|
||||
try {
|
||||
return gson.fromJson(response.getContentAsString(), type);
|
||||
} catch (JsonSyntaxException e) {
|
||||
throw new AutomowerCommunicationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForError(ContentResponse response, int statusCode) throws AutomowerCommunicationException {
|
||||
if (statusCode >= 200 && statusCode < 300) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (statusCode) {
|
||||
case HttpStatus.NOT_FOUND_404:
|
||||
throw new AutomowerCommunicationException(statusCode, "Target '" + response.getRequest().getURI()
|
||||
+ "' seems to be not available: " + response.getContentAsString());
|
||||
|
||||
case HttpStatus.FORBIDDEN_403:
|
||||
case HttpStatus.UNAUTHORIZED_401:
|
||||
throw new UnauthorizedException(statusCode, response.getContentAsString());
|
||||
|
||||
default:
|
||||
throw new AutomowerCommunicationException(statusCode, response.getContentAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public enum Activity {
|
||||
UNKNOWN,
|
||||
NOT_APPLICABLE,
|
||||
MOWING,
|
||||
GOING_HOME,
|
||||
CHARGING,
|
||||
LEAVING,
|
||||
PARKED_IN_CS,
|
||||
STOPPED_IN_GARDEN
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class Battery {
|
||||
private int batteryPercent;
|
||||
|
||||
public int getBatteryPercent() {
|
||||
return batteryPercent;
|
||||
}
|
||||
|
||||
public void setBatteryPercent(int batteryPercent) {
|
||||
this.batteryPercent = batteryPercent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class Calendar {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class Metadata {
|
||||
private boolean connected;
|
||||
private long statusTimestamp;
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
public void setConnected(boolean connected) {
|
||||
this.connected = connected;
|
||||
}
|
||||
|
||||
public long getStatusTimestamp() {
|
||||
return statusTimestamp;
|
||||
}
|
||||
|
||||
public void setStatusTimestamp(long statusTimestamp) {
|
||||
this.statusTimestamp = statusTimestamp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public enum Mode {
|
||||
MAIN_AREA,
|
||||
SECONDARY_AREA,
|
||||
HOME,
|
||||
DEMO,
|
||||
UNKNOWN
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class Mower {
|
||||
private String type;
|
||||
private String id;
|
||||
private MowerData attributes;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public MowerData getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public void setAttributes(MowerData attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class MowerApp {
|
||||
private Mode mode;
|
||||
private Activity activity;
|
||||
private State state;
|
||||
|
||||
private int errorCode;
|
||||
private long errorCodeTimestamp;
|
||||
|
||||
public Mode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void setMode(Mode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public Activity getActivity() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
public void setActivity(Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public void setErrorCode(int errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public long getErrorCodeTimestamp() {
|
||||
return errorCodeTimestamp;
|
||||
}
|
||||
|
||||
public void setErrorCodeTimestamp(long errorCodeTimestamp) {
|
||||
this.errorCodeTimestamp = errorCodeTimestamp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class MowerCommand {
|
||||
private String type;
|
||||
private MowerCommandAttributes attributes;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public MowerCommandAttributes getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public void setAttributes(MowerCommandAttributes attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class MowerCommandAttributes {
|
||||
private long duration;
|
||||
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class MowerCommandRequest {
|
||||
private MowerCommand data;
|
||||
|
||||
public MowerCommand getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(MowerCommand data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class MowerData {
|
||||
private System system;
|
||||
private Battery battery;
|
||||
private MowerApp mower;
|
||||
private Calendar calendar;
|
||||
private Planner planner;
|
||||
private Metadata metadata;
|
||||
|
||||
public System getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
||||
public void setSystem(System system) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
public Battery getBattery() {
|
||||
return battery;
|
||||
}
|
||||
|
||||
public void setBattery(Battery battery) {
|
||||
this.battery = battery;
|
||||
}
|
||||
|
||||
public MowerApp getMower() {
|
||||
return mower;
|
||||
}
|
||||
|
||||
public void setMower(MowerApp mower) {
|
||||
this.mower = mower;
|
||||
}
|
||||
|
||||
public Calendar getCalendar() {
|
||||
return calendar;
|
||||
}
|
||||
|
||||
public void setCalendar(Calendar calendar) {
|
||||
this.calendar = calendar;
|
||||
}
|
||||
|
||||
public Planner getPlanner() {
|
||||
return planner;
|
||||
}
|
||||
|
||||
public void setPlanner(Planner planner) {
|
||||
this.planner = planner;
|
||||
}
|
||||
|
||||
public Metadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class MowerListResult {
|
||||
private List<Mower> data;
|
||||
|
||||
public List<Mower> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(List<Mower> data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class MowerResult {
|
||||
private Mower data;
|
||||
|
||||
public Mower getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Mower data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class Planner {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public enum State {
|
||||
UNKNOWN,
|
||||
NOT_APPLICABLE,
|
||||
PAUSED,
|
||||
IN_OPERATION,
|
||||
WAIT_UPDATING,
|
||||
WAIT_POWER_UP,
|
||||
RESTRICTED,
|
||||
OFF,
|
||||
STOPPED,
|
||||
ERROR,
|
||||
FATAL_ERROR,
|
||||
ERROR_AT_POWER_UP
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class System {
|
||||
private String name;
|
||||
private String model;
|
||||
private String serialNumber;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public String getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
public void setSerialNumber(String serialNumber) {
|
||||
this.serialNumber = serialNumber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.exceptions;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* An exception that occurred while communicating with an automower or an automower bridge
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AutomowerCommunicationException extends IOException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private int statusCode = -1;
|
||||
|
||||
public AutomowerCommunicationException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public AutomowerCommunicationException(int statusCode, Exception e) {
|
||||
super(e);
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
public AutomowerCommunicationException(int statusCode) {
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
public AutomowerCommunicationException(int statusCode, String message) {
|
||||
super(message);
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
public AutomowerCommunicationException(String message, Exception e) {
|
||||
super(message, e);
|
||||
}
|
||||
|
||||
public AutomowerCommunicationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Rest call failed: statusCode=" + statusCode + ", message=" + super.getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + ": statusCode=" + statusCode + ", message=" + super.getMessage()
|
||||
+ ", cause: " + getCause();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.exceptions;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class UnauthorizedException extends AutomowerCommunicationException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UnauthorizedException(int statusCode, Exception e) {
|
||||
super(statusCode, e);
|
||||
}
|
||||
|
||||
public UnauthorizedException(int statusCode) {
|
||||
super(statusCode);
|
||||
}
|
||||
|
||||
public UnauthorizedException(int statusCode, String message) {
|
||||
super(statusCode, message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.rest.exceptions;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class UnavailableException extends AutomowerCommunicationException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UnavailableException(int statusCode, Exception e) {
|
||||
super(statusCode, e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.things;
|
||||
|
||||
/**
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public enum AutomowerCommand {
|
||||
|
||||
START("Start"),
|
||||
RESUME_SCHEDULE("ResumeSchedule"),
|
||||
PAUSE("Pause"),
|
||||
PARK("Park"),
|
||||
PARK_UNTIL_NEXT_SCHEDULE("ParkUntilNextSchedule"),
|
||||
PARK_UNTIL_FURTHER_NOTICE("ParkUntilFurtherNotice");
|
||||
|
||||
private final String command;
|
||||
|
||||
private AutomowerCommand(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.things;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link AutomowerConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AutomowerConfiguration {
|
||||
|
||||
public @Nullable String mowerId;
|
||||
public @Nullable Integer pollingInterval;
|
||||
|
||||
@Nullable
|
||||
public String getMowerId() {
|
||||
return mowerId;
|
||||
}
|
||||
|
||||
public void setMowerId(String mowerId) {
|
||||
this.mowerId = mowerId;
|
||||
}
|
||||
|
||||
public @Nullable Integer getPollingInterval() {
|
||||
return pollingInterval;
|
||||
}
|
||||
|
||||
public void setPollingInterval(Integer pollingInterval) {
|
||||
this.pollingInterval = pollingInterval;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.automower.internal.things;
|
||||
|
||||
import static org.openhab.binding.automower.internal.AutomowerBindingConstants.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.measure.quantity.Dimensionless;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.automower.internal.AutomowerBindingConstants;
|
||||
import org.openhab.binding.automower.internal.actions.AutomowerActions;
|
||||
import org.openhab.binding.automower.internal.bridge.AutomowerBridge;
|
||||
import org.openhab.binding.automower.internal.bridge.AutomowerBridgeHandler;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.Mower;
|
||||
import org.openhab.binding.automower.internal.rest.exceptions.AutomowerCommunicationException;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link AutomowerHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AutomowerHandler extends BaseThingHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_AUTOMOWER);
|
||||
private static final String NO_ID = "NO_ID";
|
||||
private static final long DEFAULT_COMMAND_DURATION_MIN = 60;
|
||||
private static final long DEFAULT_POLLING_INTERVAL_S = TimeUnit.MINUTES.toSeconds(10);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(AutomowerHandler.class);
|
||||
private AtomicReference<String> automowerId = new AtomicReference<String>(NO_ID);
|
||||
private long lastQueryTimeMs = 0L;
|
||||
|
||||
private @Nullable ScheduledFuture<?> automowerPollingJob;
|
||||
private long maxQueryFrequencyNanos = TimeUnit.MINUTES.toNanos(1);
|
||||
|
||||
private Runnable automowerPollingRunnable = () -> {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
|
||||
updateAutomowerState();
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
};
|
||||
|
||||
public AutomowerHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
refreshChannels(channelUID);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshChannels(ChannelUID channelUID) {
|
||||
updateAutomowerState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singleton(AutomowerActions.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
AutomowerConfiguration currentConfig = getConfigAs(AutomowerConfiguration.class);
|
||||
final String configMowerId = currentConfig.getMowerId();
|
||||
final Integer pollingIntervalS = currentConfig.getPollingInterval();
|
||||
|
||||
if (configMowerId == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/conf-error-no-mower-id");
|
||||
} else if (pollingIntervalS != null && pollingIntervalS < 1) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/conf-error-invalid-polling-interval");
|
||||
} else {
|
||||
automowerId.set(configMowerId);
|
||||
startAutomowerPolling(pollingIntervalS);
|
||||
}
|
||||
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AutomowerBridge getAutomowerBridge() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler instanceof AutomowerBridgeHandler) {
|
||||
AutomowerBridgeHandler bridgeHandler = (AutomowerBridgeHandler) handler;
|
||||
return bridgeHandler.getAutomowerBridge();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (!automowerId.get().equals(NO_ID)) {
|
||||
stopAutomowerPolling();
|
||||
automowerId.set(NO_ID);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAutomowerPolling(@Nullable Integer pollingIntervalS) {
|
||||
if (automowerPollingJob == null) {
|
||||
final long pollingIntervalToUse = pollingIntervalS == null ? DEFAULT_POLLING_INTERVAL_S : pollingIntervalS;
|
||||
automowerPollingJob = scheduler.scheduleWithFixedDelay(automowerPollingRunnable, 1, pollingIntervalToUse,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopAutomowerPolling() {
|
||||
if (automowerPollingJob != null) {
|
||||
automowerPollingJob.cancel(true);
|
||||
automowerPollingJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidResult(Mower mower) {
|
||||
return mower.getAttributes() != null && mower.getAttributes().getMetadata() != null
|
||||
&& mower.getAttributes().getBattery() != null && mower.getAttributes().getSystem() != null;
|
||||
}
|
||||
|
||||
private boolean isConnected(Mower mower) {
|
||||
return mower.getAttributes() != null && mower.getAttributes().getMetadata() != null
|
||||
&& mower.getAttributes().getMetadata().isConnected();
|
||||
}
|
||||
|
||||
private synchronized void updateAutomowerState() {
|
||||
if (System.nanoTime() - lastQueryTimeMs > maxQueryFrequencyNanos) {
|
||||
lastQueryTimeMs = System.nanoTime();
|
||||
String id = automowerId.get();
|
||||
try {
|
||||
AutomowerBridge automowerBridge = getAutomowerBridge();
|
||||
if (automowerBridge != null) {
|
||||
Mower mower = automowerBridge.getAutomowerStatus(id);
|
||||
|
||||
if (isValidResult(mower)) {
|
||||
initializeProperties(mower);
|
||||
|
||||
updateChannelState(mower);
|
||||
|
||||
if (isConnected(mower)) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/comm-error-mower-not-connected-to-cloud");
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/comm-error-query-mower-failed");
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/conf-error-no-bridge");
|
||||
}
|
||||
} catch (AutomowerCommunicationException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/comm-error-query-mower-failed");
|
||||
logger.warn("Unable to query automower status for: {}. Error: {}", id, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command to the automower with the default duration of 60min
|
||||
*
|
||||
* @param command The command that should be sent. Valid values are: "Start", "ResumeSchedule", "Pause", "Park",
|
||||
* "ParkUntilNextSchedule", "ParkUntilFurtherNotice"
|
||||
*/
|
||||
public void sendAutomowerCommand(AutomowerCommand command) {
|
||||
sendAutomowerCommand(command, DEFAULT_COMMAND_DURATION_MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command to the automower with the given duration
|
||||
*
|
||||
* @param command The command that should be sent. Valid values are: "Start", "ResumeSchedule", "Pause", "Park",
|
||||
* "ParkUntilNextSchedule", "ParkUntilFurtherNotice"
|
||||
* @param commandDurationMinutes The duration of the command in minutes. This is only evaluated for "Start" and
|
||||
* "Park" commands
|
||||
*/
|
||||
public void sendAutomowerCommand(AutomowerCommand command, long commandDurationMinutes) {
|
||||
String id = automowerId.get();
|
||||
try {
|
||||
AutomowerBridge automowerBridge = getAutomowerBridge();
|
||||
if (automowerBridge != null) {
|
||||
automowerBridge.sendAutomowerCommand(id, command, commandDurationMinutes);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "@text/conf-error-no-bridge");
|
||||
}
|
||||
} catch (AutomowerCommunicationException e) {
|
||||
logger.warn("Unable to send command to automower: {}, Error: {}", id, e.getMessage());
|
||||
}
|
||||
|
||||
updateAutomowerState();
|
||||
}
|
||||
|
||||
private void updateChannelState(Mower mower) {
|
||||
if (isValidResult(mower)) {
|
||||
updateState(CHANNEL_MOWER_NAME, new StringType(mower.getAttributes().getSystem().getName()));
|
||||
|
||||
updateState(CHANNEL_STATUS_MODE, new StringType(mower.getAttributes().getMower().getMode().name()));
|
||||
updateState(CHANNEL_STATUS_ACTIVITY, new StringType(mower.getAttributes().getMower().getActivity().name()));
|
||||
updateState(CHANNEL_STATUS_STATE, new StringType(mower.getAttributes().getMower().getState().name()));
|
||||
|
||||
Instant statusTimestamp = Instant.ofEpochMilli(mower.getAttributes().getMetadata().getStatusTimestamp());
|
||||
updateState(CHANNEL_STATUS_LAST_UPDATE,
|
||||
new DateTimeType(ZonedDateTime.ofInstant(statusTimestamp, ZoneId.systemDefault())));
|
||||
updateState(CHANNEL_STATUS_BATTERY, new QuantityType<Dimensionless>(
|
||||
mower.getAttributes().getBattery().getBatteryPercent(), SmartHomeUnits.PERCENT));
|
||||
|
||||
updateState(CHANNEL_STATUS_ERROR_CODE, new DecimalType(mower.getAttributes().getMower().getErrorCode()));
|
||||
|
||||
Instant errorCodeTimestamp = Instant.ofEpochMilli(mower.getAttributes().getMower().getErrorCodeTimestamp());
|
||||
updateState(CHANNEL_STATUS_ERROR_TIMESTAMP,
|
||||
new DateTimeType(ZonedDateTime.ofInstant(errorCodeTimestamp, ZoneId.systemDefault())));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeProperties(Mower mower) {
|
||||
Map<String, String> properties = editProperties();
|
||||
|
||||
properties.put(AutomowerBindingConstants.AUTOMOWER_ID, mower.getId());
|
||||
|
||||
if (mower.getAttributes() != null && mower.getAttributes().getSystem() != null) {
|
||||
properties.put(AutomowerBindingConstants.AUTOMOWER_SERIAL_NUMBER,
|
||||
mower.getAttributes().getSystem().getSerialNumber());
|
||||
properties.put(AutomowerBindingConstants.AUTOMOWER_MODEL, mower.getAttributes().getSystem().getModel());
|
||||
properties.put(AutomowerBindingConstants.AUTOMOWER_NAME, mower.getAttributes().getSystem().getName());
|
||||
}
|
||||
|
||||
updateProperties(properties);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="automower" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>Automower Binding</name>
|
||||
<description>Binding to interact with Husquvarna Automower robots.</description>
|
||||
<author>Markus Pfleger</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,62 @@
|
||||
# binding
|
||||
binding.automower.name = Automower
|
||||
binding.automower.description = This binding allows to interact with Husqvarna Automower robots
|
||||
|
||||
|
||||
# automower parameters
|
||||
thing-type.config.automower.automower.mowerId.label = ID
|
||||
thing-type.config.automower.automower.mowerName.label = Name
|
||||
thing-type.config.automower.automower.mowerModel.label = Model
|
||||
thing-type.config.automower.automower.mowerId.mowerSerialNumber = Serial Number
|
||||
thing-type.config.automower.automower.connected.label = Connected
|
||||
thing-type.config.automower.automower.timestamp.label = Last State Update
|
||||
thing-type.config.automower.automower.batteryPct.label = Battery Percentage
|
||||
|
||||
# channel types
|
||||
channel-type.automower.name.label = Name
|
||||
channel-type.automower.name.description = Automower name
|
||||
channel-type.automower.mode.label = Mode
|
||||
channel-type.automower.mode.description = Mode
|
||||
channel-type.automower.activity.label = Activity
|
||||
channel-type.automower.activity.description = Activity
|
||||
channel-type.automower.state.label = State
|
||||
channel-type.automower.state.description = State
|
||||
channel-type.automower.last-update.label = Last Update
|
||||
channel-type.automower.last-update.description = Last Update
|
||||
|
||||
|
||||
conf-error-no-app-key = Cannot connect to Automower bridge as no app key is available in the configuration
|
||||
conf-error-no-username = Cannot connect to Automower bridge as no username is available in the configuration
|
||||
conf-error-no-password = Cannot connect to Automower bridge as no password is available in the configuration
|
||||
conf-error-invalid-polling-interval = Invalid polling interval specified. The polling interval has to be >= 1
|
||||
|
||||
conf-error-no-mower-id = No Automower ID specified. Unable to communicate with the mower without an ID
|
||||
conf-error-no-bridge = No valid bridge for the automower is available
|
||||
|
||||
comm-error-httpclient-init-failed = Unable to initialize http client
|
||||
comm-error-query-mowers-failed = Unable to query registered mowers
|
||||
comm-error-query-mower-failed = Unable to query the automower status
|
||||
comm-error-send-mower-command-failed = Unable to send automower command
|
||||
|
||||
comm-error-mower-not-connected-to-cloud = Automower not connected to the cloud
|
||||
|
||||
action-start-label = Start
|
||||
action-start-desc = Starts the automower for a defined amount of time, overriding its schedule
|
||||
|
||||
action-pause-label = Pause
|
||||
action-pause-desc = Pauses the automower wherever it currently is
|
||||
|
||||
action-parkuntilnextschedule-label = Park until next schedule
|
||||
action-parkuntilnextschedule-desc = Parks the automower until the next schedule
|
||||
|
||||
action-parkuntilfurthernotice-label = Park until further notice
|
||||
action-parkuntilfurthernotice-desc = Parks the automower until the schedule is resumed
|
||||
|
||||
action-park-label = Park
|
||||
action-park-desc = Parks the automower for a defined amount of time, overriding its schedule
|
||||
|
||||
action-resumeschedule-label = Resume schedule
|
||||
action-resumeschedule-desc = Resumes the schedule for the automower
|
||||
|
||||
action-input-duration-label = Duration
|
||||
action-input-duration-desc = The duration of the automower command in minutes
|
||||
@@ -0,0 +1,48 @@
|
||||
binding.automower.name = Automower Binding
|
||||
binding.automower.description = Das Automower Binding erlaubt die Interaktion mit Husqvarna Automower Mährobotern mit Automower Connect Unterstützung.
|
||||
|
||||
thing-type.automower.bridge.label = Automower Connect Bridge
|
||||
thing-type.automower.bridge.description = Erlaubt die Kommunikation mit der Husqvarna Automower Connect API
|
||||
|
||||
thing-type.config.automower.bridge.appKey.label = Application Key
|
||||
thing-type.config.automower.bridge.appKey.description = Der Application Key wird für die Kommunication mit der Automower Connect API benötigt. Um diesen zu erhalten muss eine Anwendung auf der Husqvarna Website registriert werden. Diese Anwendung muss mit der "Authentication API" und der "Automower Connect API" verknüpft werden.
|
||||
|
||||
thing-type.config.automower.bridge.userName.label = Benutzername
|
||||
thing-type.config.automower.bridge.userName.description = Der Benutzername für den der Application Key ausgestellt wurde.
|
||||
|
||||
thing-type.config.automower.bridge.password.label = Passwort
|
||||
thing-type.config.automower.bridge.password.description = Das Passwort für den angegebenen Benutzer.
|
||||
|
||||
thing-type.config.automower.bridge.pollingInterval.label = Polling Intervall
|
||||
thing-type.config.automower.bridge.pollingInterval.description = Das Intervall in dem die Verbindung mit dem Automower Connect API überprüft werden soll. Der Standardwert ist 3600s (1h)
|
||||
|
||||
|
||||
thing-type.automower.automower.label = Automower
|
||||
thing-type.automower.automower.description = Ein Husqvarna Automower
|
||||
|
||||
thing-type.config.automower.automower.mowerId.label = Automower Id
|
||||
thing-type.config.automower.automower.mowerId.label = Die interne ID des Automowers die von der Automower Connect API benutzt wird um einen Automower zu identifizieren
|
||||
|
||||
thing-type.config.automower.automower.pollingInterval.label = Polling Intervall
|
||||
thing-type.config.automower.automower.pollingInterval.label = Das Intervall in dem der Status des Automowers abgefragt werden soll. Der Standardwert ist 300s (5min)
|
||||
|
||||
action-start-label = Start
|
||||
action-start-desc = Startet den Automower für die angegebene Zeit, unabhängig vom Zeitplan
|
||||
|
||||
action-pause-label = Pause
|
||||
action-pause-desc = Pausiert den Automower wo immer er gerade ist
|
||||
|
||||
action-parkuntilnextschedule-label = Parken (laut Zeitplan)
|
||||
action-parkuntilnextschedule-desc = Parkt den Automower uns setzt den Zeitplan fort sobald er geladen wurde
|
||||
|
||||
action-parkuntilfurthernotice-label = Parken (bis auf weiteres)
|
||||
action-parkuntilfurthernotice-desc = Parkt den Automower bis auf weiteres
|
||||
|
||||
action-park-label = Parken
|
||||
action-park-desc = Parkt den Automower für die angegebene Zeit, unabhängig vom Zeitplan
|
||||
|
||||
action-resumeschedule-label = Start (Zeitplan fortsetzen)
|
||||
action-resumeschedule-desc = Startet den Automower und setzt den Zeitplan fort
|
||||
|
||||
action-input-duration-label = Duration
|
||||
action-input-duration-desc = The duration of the automower command in minutes
|
||||
@@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="automower"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Automower Bridge Thing Type -->
|
||||
<bridge-type id="bridge">
|
||||
<label>Automower Connect Bridge</label>
|
||||
<description>The bridge to communicate with the Automower Connect API</description>
|
||||
|
||||
<config-description>
|
||||
<parameter name="appKey" type="text" required="true">
|
||||
<label>Application Key</label>
|
||||
<description>The Application Key is required to communication with the Automower Connect Api. It can be obtained by
|
||||
registering an Application on the Husqvarna Website. This application also needs to be connected to the
|
||||
"Authentication API" and the "Automower Connect API"</description>
|
||||
</parameter>
|
||||
<parameter name="userName" type="text" required="true">
|
||||
<label>User Name</label>
|
||||
<description>The user name for which the application key has been issued</description>
|
||||
</parameter>
|
||||
<parameter name="password" type="text" required="true">
|
||||
<context>Password</context>
|
||||
<description>The password for the given user</description>
|
||||
</parameter>
|
||||
<parameter name="pollingInterval" type="integer" required="false" unit="s">
|
||||
<label>Polling Interval</label>
|
||||
<default>3600</default>
|
||||
<description>How often the available automowers should be queried in seconds</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</bridge-type>
|
||||
|
||||
<!-- Automower Thing Type -->
|
||||
<thing-type id="automower">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Automower</label>
|
||||
<description>An automatic lawn mower</description>
|
||||
|
||||
<channels>
|
||||
<channel id="name" typeId="nameType"/>
|
||||
<channel id="mode" typeId="modeType"/>
|
||||
<channel id="activity" typeId="activityType"/>
|
||||
<channel id="state" typeId="stateType"/>
|
||||
<channel id="last-update" typeId="lastUpdateType"/>
|
||||
<channel id="battery" typeId="batteryType"/>
|
||||
<channel id="error-code" typeId="errorCodeType"/>
|
||||
<channel id="error-timestamp" typeId="errorTimestampType"/>
|
||||
</channels>
|
||||
|
||||
<properties>
|
||||
<property name="mowerId">N/A</property>
|
||||
<property name="mowerName">N/A</property>
|
||||
<property name="mowerModel">N/A</property>
|
||||
<property name="mowerSerialNumber">N/A</property>
|
||||
</properties>
|
||||
|
||||
<config-description>
|
||||
<parameter name="mowerId" type="text" required="true">
|
||||
<label>Automower Id</label>
|
||||
<description>The Id of an automower as used by the Automower Connect Api to identify a mower</description>
|
||||
</parameter>
|
||||
<parameter name="pollingInterval" type="integer" required="false" unit="s">
|
||||
<label>Polling Interval</label>
|
||||
<default>600</default>
|
||||
<description>How often the current automower state should be polled in seconds</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="nameType">
|
||||
<item-type>String</item-type>
|
||||
<label>Automower Name</label>
|
||||
<description>The channel providing the automower name</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="modeType">
|
||||
<item-type>String</item-type>
|
||||
<label>Mode</label>
|
||||
<description>The current mode</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="MAIN_AREA">Main Area</option>
|
||||
<option value="SECONDARY_AREA">Secondary Area</option>
|
||||
<option value="HOME">Home</option>
|
||||
<option value="DEMO">Demo</option>
|
||||
<option value="UNKNOWN">Unknown</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="activityType">
|
||||
<item-type>String</item-type>
|
||||
<label>Activity</label>
|
||||
<description>The current activity</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="UNKNOWN">Unknown</option>
|
||||
<option value="NOT_APPLICABLE">N/A</option>
|
||||
<option value="MOWING">Mowing</option>
|
||||
<option value="GOING_HOME">Returning to charging station</option>
|
||||
<option value="CHARGING">Charging</option>
|
||||
<option value="LEAVING">Leaving charging station</option>
|
||||
<option value="PARKED_IN_CS">Parked in charging station</option>
|
||||
<option value="STOPPED_IN_GARDEN">Stopped in garden</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="stateType">
|
||||
<item-type>String</item-type>
|
||||
<label>State</label>
|
||||
<description>The current state</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="UNKNOWN">Unknown</option>
|
||||
<option value="NOT_APPLICABLE">N/A</option>
|
||||
<option value="PAUSED">Paused by user</option>
|
||||
<option value="IN_OPERATION">Working</option>
|
||||
<option value="WAIT_UPDATING">Downloading new firmware</option>
|
||||
<option value="WAIT_POWER_UP">Booting mower</option>
|
||||
<option value="RESTRICTED">Waiting</option>
|
||||
<option value="OFF">Off</option>
|
||||
<option value="STOPPED">Stopped- Manual intervention required</option>
|
||||
<option value="ERROR">Error</option>
|
||||
<option value="FATAL_ERROR">Fatal error</option>
|
||||
<option value="ERROR_AT_POWER_UP">Boot error</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="lastUpdateType">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Last Update</label>
|
||||
<description>The time when the mower sent the last update</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="batteryType">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Battery</label>
|
||||
<description>The battery level of the mower at the time of last update</description>
|
||||
<state readOnly="true" pattern="%d %%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="errorCodeType">
|
||||
<item-type>Number</item-type>
|
||||
<label>Error Code</label>
|
||||
<description>The error code at the time of last update</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="errorTimestampType">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Error Time</label>
|
||||
<description>The time when the error occurred</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user