2 * Copyright (c) 2010-2021 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.boschshc.internal.services;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.TimeoutException;
17 import java.util.function.Consumer;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.boschshc.internal.devices.bridge.BoschSHCBridgeHandler;
22 import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
23 import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import com.google.gson.Gson;
28 import com.google.gson.JsonElement;
31 * Base class of a service of a Bosch Smart Home device.
32 * The services of the devices and their official APIs can be found here: https://apidocs.bosch-smarthome.com/local/
34 * @author Christian Oeing - Initial contribution
37 public abstract class BoschSHCService<TState extends BoschSHCServiceState> {
39 private final Logger logger = LoggerFactory.getLogger(BoschSHCService.class);
44 private final String serviceName;
47 * Class of service state
49 private final Class<TState> stateClass;
52 * gson instance to convert a class to json string and back.
54 private final Gson gson = new Gson();
57 * Bridge to use for communication from/to the device
59 private @Nullable BoschSHCBridgeHandler bridgeHandler;
62 * Id of device the service belongs to
64 private @Nullable String deviceId;
67 * Function to call after receiving state updates from the device
69 private @Nullable Consumer<TState> stateUpdateListener;
74 * @param serviceName Unique name of the service.
75 * @param stateClass State class that this service uses for data transfers from/to the device.
77 protected BoschSHCService(String serviceName, Class<TState> stateClass) {
78 this.serviceName = serviceName;
79 this.stateClass = stateClass;
83 * Initializes the service
85 * @param bridgeHandler Bridge to use for communication from/to the device
86 * @param deviceId Id of device this service is for
87 * @param stateUpdateListener Function to call when a state update was received from the device.
89 public void initialize(BoschSHCBridgeHandler bridgeHandler, String deviceId,
90 @Nullable Consumer<TState> stateUpdateListener) {
91 this.bridgeHandler = bridgeHandler;
92 this.deviceId = deviceId;
93 this.stateUpdateListener = stateUpdateListener;
97 * Returns the unique name of this service.
99 * @return Unique name of the service.
101 public String getServiceName() {
102 return this.serviceName;
106 * Returns the class of the state this service provides.
108 * @return Class of the state this service provides.
110 public Class<TState> getStateClass() {
111 return this.stateClass;
115 * Requests the current state of the service and updates it.
117 * @throws ExecutionException
118 * @throws TimeoutException
119 * @throws InterruptedException
120 * @throws BoschSHCException
122 public void refreshState() throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
124 TState state = this.getState();
126 this.onStateUpdate(state);
131 * Requests the current state of the device with the specified id.
133 * @return Current state of the device.
134 * @throws ExecutionException
135 * @throws TimeoutException
136 * @throws InterruptedException
137 * @throws BoschSHCException
139 public @Nullable TState getState()
140 throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
141 String deviceId = this.deviceId;
142 if (deviceId == null) {
145 BoschSHCBridgeHandler bridgeHandler = this.bridgeHandler;
146 if (bridgeHandler == null) {
149 return bridgeHandler.getState(deviceId, this.serviceName, this.stateClass);
153 * Sets the state of the device with the specified id.
155 * @param state State to set.
156 * @throws InterruptedException
157 * @throws ExecutionException
158 * @throws TimeoutException
160 public void setState(TState state) throws InterruptedException, TimeoutException, ExecutionException {
161 String deviceId = this.deviceId;
162 if (deviceId == null) {
165 BoschSHCBridgeHandler bridgeHandler = this.bridgeHandler;
166 if (bridgeHandler == null) {
169 bridgeHandler.putState(deviceId, this.serviceName, state);
173 * A state update was received from the bridge
175 * @param stateData Current state of service. Serialized as JSON.
177 public void onStateUpdate(JsonElement stateData) {
179 TState state = gson.fromJson(stateData, this.stateClass);
181 this.logger.warn("Received invalid, expected type {}", this.stateClass.getName());
184 this.onStateUpdate(state);
188 * A state update was received from the bridge.
190 * @param state Current state of service as an instance of the state class.
192 private void onStateUpdate(TState state) {
193 Consumer<TState> stateUpdateListener = this.stateUpdateListener;
194 if (stateUpdateListener != null) {
195 stateUpdateListener.accept(state);