2 * Copyright (c) 2010-2024 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;
47 public AbstractWriteCommand(EaseeThingHandler handler, Channel channel, Command command,
48 RetryOnFailure retryOnFailure, ProcessFailureResponse processFailureResponse,
49 JsonResultProcessor resultProcessor) {
50 super(handler, retryOnFailure, processFailureResponse, resultProcessor);
51 this.channel = channel;
52 this.command = command;
56 * helper method for write commands that extracts value from command.
58 * @return value as String without unit.
60 protected String getCommandValue() {
61 if (command instanceof QuantityType<?> quantityCommand) {
62 // this is necessary because we must not send the unit to the backend
63 return String.valueOf(quantityCommand.doubleValue());
64 } else if (command instanceof OnOffType) {
65 // this is necessary because we must send booleans and not ON/OFF to the backend
66 return String.valueOf(command.equals(OnOffType.ON));
68 return command.toString();
73 * helper that transforms channelId + commandvalue in a JSON string that can be added as content to a POST request.
75 * @return converted JSON string
76 * @throws ValidationException
78 protected String getJsonContent() throws ValidationException {
79 Map<String, String> content = new HashMap<String, String>(1);
80 content.put(channel.getUID().getIdWithoutGroup(), getCommandValue());
82 return gson.toJson(content);
86 protected Request prepareRequest(Request requestToPrepare) throws ValidationException {
87 String channelId = channel.getUID().getIdWithoutGroup();
88 String expr = Utils.getValidationExpression(channel);
89 String value = getCommandValue();
91 // quantity types are transformed to double and thus we might have decimals which could cause validation error.
92 // So we will shorten here in case no decimals are needed.
93 if (value.endsWith(".0")) {
94 value = value.substring(0, value.length() - 2);
97 if (value.matches(expr)) {
98 return prepareWriteRequest(requestToPrepare);
100 logger.info("channel '{}' does not allow value '{}' - validation rule '{}'", channelId, value, expr);
101 throw new ValidationException("channel (" + channelId + ") could not be updated due to a validation error");
106 protected String getChannelGroup() {
107 // this is a pure write command, thus no channel group needed.
108 return CHANNEL_GROUP_NONE;
112 * concrete implementation has to prepare the write requests with additional parameters, etc
114 * @param requestToPrepare the request to prepare
115 * @return prepared Request object
116 * @throws ValidationException
118 protected abstract Request prepareWriteRequest(Request requestToPrepare) throws ValidationException;