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.easee.internal.command;
15 import static org.openhab.binding.easee.internal.EaseeBindingConstants.CHANNEL_GROUP_NONE;
17 import java.util.HashMap;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jetty.client.api.Request;
22 import org.openhab.binding.easee.internal.Utils;
23 import org.openhab.binding.easee.internal.handler.EaseeThingHandler;
24 import org.openhab.binding.easee.internal.model.ValidationException;
25 import org.openhab.core.library.types.OnOffType;
26 import org.openhab.core.library.types.QuantityType;
27 import org.openhab.core.thing.Channel;
28 import org.openhab.core.types.Command;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * base class for all write commands. common logic should be implemented here
35 * @author Alexander Friese - initial contribution
38 public abstract class AbstractWriteCommand extends AbstractCommand {
39 private final Logger logger = LoggerFactory.getLogger(AbstractWriteCommand.class);
41 protected final Channel channel;
42 protected Command command;
49 public AbstractWriteCommand(EaseeThingHandler handler, Channel channel, Command command,
50 RetryOnFailure retryOnFailure, ProcessFailureResponse processFailureResponse) {
51 super(handler, retryOnFailure, processFailureResponse);
52 this.channel = channel;
53 this.command = command;
57 * helper method for write commands that extracts value from command.
59 * @return value as String without unit.
61 protected String getCommandValue() {
62 if (command instanceof QuantityType<?>) {
63 // this is necessary because we must not send the unit to the backend
64 return String.valueOf(((QuantityType<?>) command).doubleValue());
65 } else if (command instanceof OnOffType) {
66 // this is necessary because we must send booleans and not ON/OFF to the backend
67 return String.valueOf(command.equals(OnOffType.ON));
69 return command.toString();
74 * helper that transforms channelId + commandvalue in a JSON string that can be added as content to a POST request.
76 * @return converted JSON string
77 * @throws ValidationException
79 protected String getJsonContent() throws ValidationException {
80 Map<String, String> content = new HashMap<String, String>(1);
81 content.put(channel.getUID().getIdWithoutGroup(), getCommandValue());
83 return gson.toJson(content);
87 protected Request prepareRequest(Request requestToPrepare) throws ValidationException {
88 String channelId = channel.getUID().getIdWithoutGroup();
89 String expr = Utils.getValidationExpression(channel);
90 String value = getCommandValue();
92 // quantity types are transformed to double and thus we might have decimals which could cause validation error.
93 // So we will shorten here in case no decimals are needed.
94 if (value.endsWith(".0")) {
95 value = value.substring(0, value.length() - 2);
98 if (value.matches(expr)) {
99 return prepareWriteRequest(requestToPrepare);
101 logger.info("channel '{}' does not allow value '{}' - validation rule '{}'", channelId, value, expr);
102 throw new ValidationException("channel (" + channelId + ") could not be updated due to a validation error");
107 protected String getChannelGroup() {
108 // this is a pure write command, thus no channel group needed.
109 return CHANNEL_GROUP_NONE;
113 * concrete implementation has to prepare the write requests with additional parameters, etc
115 * @param requestToPrepare the request to prepare
116 * @return prepared Request object
117 * @throws ValidationException
119 protected abstract Request prepareWriteRequest(Request requestToPrepare) throws ValidationException;