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 JsonResultProcessor resultProcessor) {
52 super(handler, retryOnFailure, processFailureResponse, resultProcessor);
53 this.channel = channel;
54 this.command = command;
58 * helper method for write commands that extracts value from command.
60 * @return value as String without unit.
62 protected String getCommandValue() {
63 if (command instanceof QuantityType<?> quantityCommand) {
64 // this is necessary because we must not send the unit to the backend
65 return String.valueOf(quantityCommand.doubleValue());
66 } else if (command instanceof OnOffType) {
67 // this is necessary because we must send booleans and not ON/OFF to the backend
68 return String.valueOf(command.equals(OnOffType.ON));
70 return command.toString();
75 * helper that transforms channelId + commandvalue in a JSON string that can be added as content to a POST request.
77 * @return converted JSON string
78 * @throws ValidationException
80 protected String getJsonContent() throws ValidationException {
81 Map<String, String> content = new HashMap<String, String>(1);
82 content.put(channel.getUID().getIdWithoutGroup(), getCommandValue());
84 return gson.toJson(content);
88 protected Request prepareRequest(Request requestToPrepare) throws ValidationException {
89 String channelId = channel.getUID().getIdWithoutGroup();
90 String expr = Utils.getValidationExpression(channel);
91 String value = getCommandValue();
93 // quantity types are transformed to double and thus we might have decimals which could cause validation error.
94 // So we will shorten here in case no decimals are needed.
95 if (value.endsWith(".0")) {
96 value = value.substring(0, value.length() - 2);
99 if (value.matches(expr)) {
100 return prepareWriteRequest(requestToPrepare);
102 logger.info("channel '{}' does not allow value '{}' - validation rule '{}'", channelId, value, expr);
103 throw new ValidationException("channel (" + channelId + ") could not be updated due to a validation error");
108 protected String getChannelGroup() {
109 // this is a pure write command, thus no channel group needed.
110 return CHANNEL_GROUP_NONE;
114 * concrete implementation has to prepare the write requests with additional parameters, etc
116 * @param requestToPrepare the request to prepare
117 * @return prepared Request object
118 * @throws ValidationException
120 protected abstract Request prepareWriteRequest(Request requestToPrepare) throws ValidationException;