import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Handler for physical Bosch devices with configurable IDs (as opposed to system services, which have static IDs).
@NonNullByDefault
public abstract class BoschSHCDeviceHandler extends BoschSHCHandler {
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
/**
* Bosch SHC configuration loaded from openHAB configuration.
*/
private @Nullable BoschSHCConfiguration config;
- public BoschSHCDeviceHandler(Thing thing) {
+ protected BoschSHCDeviceHandler(Thing thing) {
super(thing);
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.gson.Gson;
import com.google.gson.JsonElement;
/**
public final Collection<String> affectedChannels;
}
- /**
- * Reusable gson instance to convert a class to json string and back in derived classes.
- */
- protected static final Gson GSON = new Gson();
-
- protected final Logger logger = LoggerFactory.getLogger(getClass());
+ private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* Services of the device.
*/
private <TState extends BoschSHCServiceState> void registerService(BoschSHCService<TState> service,
Collection<String> affectedChannels) {
- this.services.add(new DeviceService<TState>(service, affectedChannels));
+ this.services.add(new DeviceService<>(service, affectedChannels));
}
/**
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
+import org.openhab.binding.boschshc.internal.serialization.GsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
/**
*/
@NonNullByDefault
public class BoschHttpClient extends HttpClient {
- private static final Gson GSON = new Gson();
- private final Logger logger = LoggerFactory.getLogger(BoschHttpClient.class);
+ private final Logger logger = LoggerFactory.getLogger(getClass());
private final String ipAddress;
private final String systemPassword;
logger.debug("Online check failed with status code: {}", contentResponse.getStatus());
return false;
}
- } catch (TimeoutException | ExecutionException | NullPointerException e) {
- logger.debug("Online check failed because of {}!", e.getMessage());
+ } catch (InterruptedException e) {
+ throw e;
+ } catch (Exception e) {
+ logger.debug("Online check failed because of {}!", e.getMessage(), e);
return false;
}
}
logger.debug("Access check failed with status code: {}", contentResponse.getStatus());
return false;
}
- } catch (TimeoutException | ExecutionException | NullPointerException e) {
- logger.debug("Access check failed because of {}!", e.getMessage());
+ } catch (InterruptedException e) {
+ throw e;
+ } catch (Exception e) {
+ logger.debug("Access check failed because of {}!", e.getMessage(), e);
return false;
}
}
logger.info("Pairing failed with response status {}.", contentResponse.getStatus());
return false;
}
- } catch (TimeoutException | CertificateEncodingException | KeyStoreException | NullPointerException e) {
- logger.warn("Pairing failed with exception {}", e.getMessage());
+ } catch (TimeoutException | CertificateEncodingException | KeyStoreException | RuntimeException e) {
+ logger.warn("Pairing failed with exception {}", e.getMessage(), e);
return false;
} catch (ExecutionException e) {
// javax.net.ssl.SSLHandshakeException: General SSLEngine problem
* @return created HTTP request instance
*/
public Request createRequest(String url, HttpMethod method, @Nullable Object content) {
- logger.trace("Create request for http client {}", this.toString());
+ logger.trace("Create request for http client {}", this);
Request request = this.newRequest(url).method(method).header("Content-Type", "application/json")
.header("api-version", "2.1") // see https://github.com/BoschSmartHome/bosch-shc-api-docs/issues/46
.timeout(10, TimeUnit.SECONDS); // Set default timeout
if (content != null) {
- String body = GSON.toJson(content);
- logger.trace("create request for {} and content {}", url, content.toString());
+ String body = GsonUtils.DEFAULT_GSON_INSTANCE.toJson(content);
+ logger.trace("create request for {} and content {}", url, content);
request = request.content(new StringContentProvider(body));
} else {
logger.trace("create request for {}", url);
Predicate<TContent> contentValidator,
@Nullable BiFunction<Integer, String, BoschSHCException> errorResponseHandler)
throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException {
- logger.trace("Send request: {}", request.toString());
+ logger.trace("Send request: {}", request);
ContentResponse contentResponse = request.send();
try {
@Nullable
- TContent content = GSON.fromJson(textContent, responseContentClass);
+ TContent content = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(textContent, responseContentClass);
if (content == null) {
throw new ExecutionException(String.format("Received no content in response, expected type %s",
responseContentClass.getName()), null);
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
import org.openhab.binding.boschshc.internal.exceptions.LongPollingFailedException;
import org.openhab.binding.boschshc.internal.exceptions.PairingFailedException;
+import org.openhab.binding.boschshc.internal.serialization.GsonUtils;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
import org.openhab.binding.boschshc.internal.services.dto.JsonRestExceptionResponse;
import org.openhab.core.thing.Bridge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
private final Logger logger = LoggerFactory.getLogger(BridgeHandler.class);
- /**
- * gson instance to convert a class to json string and back.
- */
- private final Gson gson = new Gson();
-
/**
* Handler to do long polling.
*/
// prepare SSL key and certificates
factory = new BoschSslUtil(ipAddress).getSslContextFactory();
} catch (PairingFailedException e) {
+ logger.debug("Error while obtaining SSL context factory.", e);
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
"@text/offline.conf-error-ssl");
return;
try {
httpClient.stop();
} catch (Exception e) {
- logger.debug("HttpClient failed on bridge disposal: {}", e.getMessage());
+ logger.debug("HttpClient failed on bridge disposal: {}", e.getMessage(), e);
}
this.httpClient = null;
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
+ // commands are handled by individual device handlers
}
/**
// start long polling loop
this.updateStatus(ThingStatus.ONLINE);
- try {
- this.longPolling.start(httpClient);
- } catch (LongPollingFailedException e) {
- this.handleLongPollFailure(e);
- }
+ startLongPolling(httpClient);
} catch (InterruptedException e) {
this.updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.UNKNOWN.NONE, "@text/offline.interrupted");
}
}
+ private void startLongPolling(BoschHttpClient httpClient) {
+ try {
+ this.longPolling.start(httpClient);
+ } catch (LongPollingFailedException e) {
+ this.handleLongPollFailure(e);
+ }
+ }
+
/**
* Check the bridge access by sending an HTTP request.
* Does not throw any exception in case the request fails.
Type collectionType = new TypeToken<ArrayList<Device>>() {
}.getType();
- @Nullable
- List<Device> nullableDevices = gson.fromJson(content, collectionType);
+ List<Device> nullableDevices = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(content, collectionType);
return Optional.ofNullable(nullableDevices).orElse(Collections.emptyList());
} catch (TimeoutException | ExecutionException e) {
- logger.debug("Request devices failed because of {}!", e.getMessage());
+ logger.debug("Request devices failed because of {}!", e.getMessage(), e);
return Collections.emptyList();
}
}
Type collectionType = new TypeToken<ArrayList<Room>>() {
}.getType();
- ArrayList<Room> rooms = gson.fromJson(content, collectionType);
+ ArrayList<Room> rooms = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(content, collectionType);
return Objects.requireNonNullElse(rooms, emptyRooms);
} catch (TimeoutException | ExecutionException e) {
logger.debug("Request rooms failed because of {}!", e.getMessage());
// the battery level service receives no individual state object but rather requires the DeviceServiceData
// structure
if ("BatteryLevel".equals(deviceServiceData.id)) {
- return gson.toJsonTree(deviceServiceData);
+ return GsonUtils.DEFAULT_GSON_INSTANCE.toJsonTree(deviceServiceData);
}
return deviceServiceData.state;
// All children of this should implement BoschSHCHandler
@Nullable
ThingHandler baseHandler = childThing.getHandler();
- if (baseHandler != null && baseHandler instanceof BoschSHCHandler) {
- BoschSHCHandler handler = (BoschSHCHandler) baseHandler;
+ if (baseHandler instanceof BoschSHCHandler handler) {
@Nullable
String deviceId = handler.getBoschID();
Request request = httpClient.createRequest(url, GET);
return httpClient.sendRequest(request, Device.class, Device::isValid, (Integer statusCode, String content) -> {
- JsonRestExceptionResponse errorResponse = gson.fromJson(content, JsonRestExceptionResponse.class);
+ JsonRestExceptionResponse errorResponse = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(content,
+ JsonRestExceptionResponse.class);
if (errorResponse != null && JsonRestExceptionResponse.isValid(errorResponse)) {
if (errorResponse.errorCode.equals(JsonRestExceptionResponse.ENTITY_NOT_FOUND)) {
return new BoschSHCException("@text/offline.conf-error.invalid-device-id");
int statusCode = contentResponse.getStatus();
if (statusCode != 200) {
- JsonRestExceptionResponse errorResponse = gson.fromJson(content, JsonRestExceptionResponse.class);
+ JsonRestExceptionResponse errorResponse = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(content,
+ JsonRestExceptionResponse.class);
if (errorResponse != null) {
throw new BoschSHCException(
String.format("State request with URL %s failed with status code %d and error code %s", url,
import org.openhab.binding.boschshc.internal.devices.bridge.dto.SubscribeResult;
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
import org.openhab.binding.boschshc.internal.exceptions.LongPollingFailedException;
+import org.openhab.binding.boschshc.internal.serialization.GsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.gson.Gson;
-
/**
* Handles the long polling to the Smart Home Controller.
*
private final Logger logger = LoggerFactory.getLogger(LongPolling.class);
- /**
- * gson instance to convert a class to json string and back.
- */
- private final Gson gson = new Gson();
-
/**
* Executor to schedule long polls.
*/
private String subscribe(BoschHttpClient httpClient) throws LongPollingFailedException {
try {
String url = httpClient.getBoschShcUrl("remote/json-rpc");
- JsonRpcRequest request = new JsonRpcRequest("2.0", "RE/subscribe",
+ JsonRpcRequest subscriptionRequest = new JsonRpcRequest("2.0", "RE/subscribe",
new String[] { "com/bosch/sh/remote/*", null });
- logger.debug("Subscribe: Sending request: {} - using httpClient {}", request.toString(),
- httpClient.toString());
- Request httpRequest = httpClient.createRequest(url, POST, request);
+ logger.debug("Subscribe: Sending request: {} - using httpClient {}", subscriptionRequest, httpClient);
+ Request httpRequest = httpClient.createRequest(url, POST, subscriptionRequest);
SubscribeResult response = httpClient.sendRequest(httpRequest, SubscribeResult.class,
SubscribeResult::isValid, null);
logger.debug("Subscribe: Got subscription ID: {} {}", response.getResult(), response.getJsonrpc());
- String subscriptionId = response.getResult();
- return subscriptionId;
+ return response.getResult();
} catch (TimeoutException | ExecutionException | BoschSHCException e) {
throw new LongPollingFailedException(
String.format("Error on subscribe (Http client: %s): %s", httpClient.toString(), e.getMessage()),
this.executeLongPoll(httpClient, subscriptionId);
} catch (LongPollingFailedException e) {
this.handleFailure.accept(e);
- return;
}
}
JsonRpcRequest requestContent = new JsonRpcRequest("2.0", "RE/longPoll", new String[] { subscriptionId, "20" });
String url = httpClient.getBoschShcUrl("remote/json-rpc");
- Request request = httpClient.createRequest(url, POST, requestContent);
+ Request longPollRequest = httpClient.createRequest(url, POST, requestContent);
// Long polling responds after 20 seconds with an empty response if no update has happened.
// 10 second threshold was added to not time out if response from controller takes a bit longer than 20 seconds.
- request.timeout(30, TimeUnit.SECONDS);
+ longPollRequest.timeout(30, TimeUnit.SECONDS);
- this.request = request;
+ this.request = longPollRequest;
LongPolling longPolling = this;
- request.send(new BufferingResponseListener() {
+ longPollRequest.send(new BufferingResponseListener() {
@Override
public void onComplete(@Nullable Result result) {
// NOTE: This handler runs inside the HTTP thread, so we schedule the response handling in a new thread
// Check if response was failure or success
Throwable failure = result != null ? result.getFailure() : null;
if (failure != null) {
- if (failure instanceof ExecutionException) {
- if (failure.getCause() instanceof AbortLongPolling) {
- logger.debug("Canceling long polling for subscription id {} because it was aborted",
- subscriptionId);
- } else {
- this.handleFailure.accept(new LongPollingFailedException(
- "Unexpected exception during long polling request", failure));
- }
- } else {
- this.handleFailure.accept(
- new LongPollingFailedException("Unexpected exception during long polling request", failure));
- }
+ handleLongPollFailure(subscriptionId, failure);
} else {
logger.debug("Long poll response: {}", content);
String nextSubscriptionId = subscriptionId;
- LongPollResult longPollResult = gson.fromJson(content, LongPollResult.class);
+ LongPollResult longPollResult = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(content, LongPollResult.class);
if (longPollResult != null && longPollResult.result != null) {
this.handleResult.accept(longPollResult);
} else {
logger.debug("Long poll response contained no result: {}", content);
// Check if we got a proper result from the SHC
- LongPollError longPollError = gson.fromJson(content, LongPollError.class);
+ LongPollError longPollError = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(content, LongPollError.class);
if (longPollError != null && longPollError.error != null) {
logger.debug("Got long poll error: {} (code: {})", longPollError.error.message,
}
}
+ private void handleLongPollFailure(String subscriptionId, Throwable failure) {
+ if (failure instanceof ExecutionException) {
+ if (failure.getCause() instanceof AbortLongPolling) {
+ logger.debug("Canceling long polling for subscription id {} because it was aborted", subscriptionId);
+ } else {
+ this.handleFailure.accept(
+ new LongPollingFailedException("Unexpected exception during long polling request", failure));
+ }
+ } else {
+ this.handleFailure.accept(
+ new LongPollingFailedException("Unexpected exception during long polling request", failure));
+ }
+ }
+
@SuppressWarnings("serial")
private class AbortLongPolling extends BoschSHCException {
}
*/
package org.openhab.binding.boschshc.internal.devices.climatecontrol;
-import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_SETPOINT_TEMPERATURE;
-import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.CHANNEL_TEMPERATURE;
+import static org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants.*;
import java.util.List;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.types.Command;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A virtual device which controls up to six Bosch Smart Home radiator thermostats in a room.
- *
+ *
* @author Christian Oeing - Initial contribution
*/
@NonNullByDefault
public final class ClimateControlHandler extends BoschSHCDeviceHandler {
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
private RoomClimateControlService roomClimateControlService;
/**
* Constructor.
- *
+ *
* @param thing The Bosch Smart Home device that should be handled.
*/
public ClimateControlHandler(Thing thing) {
/**
* Updates the channels which are linked to the {@link TemperatureLevelService} of the device.
- *
+ *
* @param state Current state of {@link TemperatureLevelService}.
*/
private void updateChannels(TemperatureLevelServiceState state) {
/**
* Updates the channels which are linked to the {@link RoomClimateControlService} of the device.
- *
+ *
* @param state Current state of {@link RoomClimateControlService}.
*/
private void updateChannels(RoomClimateControlServiceState state) {
/**
* Sets the desired temperature for the device.
- *
+ *
* @param quantityType Command which contains the new desired temperature.
*/
private void updateSetpointTemperature(QuantityType<?> quantityType) {
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.types.Command;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Control of your shutter to take any position you desire.
- *
+ *
* @author Christian Oeing - Initial contribution
*/
@NonNullByDefault
}
}
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
private ShutterControlService shutterControlService;
public ShutterControlHandler(Thing thing) {
*/
package org.openhab.binding.boschshc.internal.discovery;
-import java.util.*;
+import java.util.AbstractMap;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@Override
public void setThingHandler(@Nullable ThingHandler handler) {
- if (handler instanceof BridgeHandler) {
+ if (handler instanceof BridgeHandler bridgeHandler) {
logger.trace("Set bridge handler {}", handler);
- shcBridgeHandler = (BridgeHandler) handler;
+ shcBridgeHandler = bridgeHandler;
}
}
}
private String getNiceName(String name, String roomName) {
- if (!name.startsWith("-"))
+ if (!name.startsWith("-")) {
return name;
+ }
// convert "-IntrusionDetectionSystem-" into "Intrusion Detection System"
// convert "-RoomClimateControl-" into "Room Climate Control myRoomName"
--- /dev/null
+/**
+ * Copyright (c) 2010-2023 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.boschshc.internal.serialization;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * Utilities for JSON serialization and deserialization using Google Gson.
+ *
+ * @author David Pace - Initial contribution
+ *
+ */
+@NonNullByDefault
+public final class GsonUtils {
+ private GsonUtils() {
+ // Utility Class
+ }
+
+ /**
+ * The default Gson instance to be used for serialization and deserialization.
+ * <p>
+ * This instance does not serialize or deserialize fields named <code>logger</code>.
+ */
+ public static final Gson DEFAULT_GSON_INSTANCE = new GsonBuilder()
+ .addSerializationExclusionStrategy(new LoggerExclusionStrategy())
+ .addDeserializationExclusionStrategy(new LoggerExclusionStrategy()).create();
+}
--- /dev/null
+/**
+ * Copyright (c) 2010-2023 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.boschshc.internal.serialization;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.FieldAttributes;
+
+/**
+ * A GSON exclusion strategy that prevents loggers from being serialized and deserialized.
+ *
+ * @author David Pace - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class LoggerExclusionStrategy implements ExclusionStrategy {
+
+ @Override
+ public boolean shouldSkipField(@NonNullByDefault({}) FieldAttributes f) {
+ return "logger".equalsIgnoreCase(f.getName());
+ }
+
+ @Override
+ public boolean shouldSkipClass(@NonNullByDefault({}) Class<?> clazz) {
+ return false;
+ }
+}
* <p>
* The endpoints to retrieve system states are different from the ones for physical devices, i.e. they do not follow the
* pattern
- *
+ *
* <pre>
* https://{IP}:8444/smarthome/devices/{deviceId}/services/{serviceName}/state
* </pre>
- *
+ *
* Instead, system services have endpoints like
- *
+ *
* <pre>
* /intrusion/states/system
* </pre>
- *
+ *
* <p>
* The services of the devices and their official APIs can be found
* <a href="https://apidocs.bosch-smarthome.com/local/">here</a>.
*
* @param <TState> type used for representing the service state
- *
+ *
* @author David Pace - Initial contribution
*/
@NonNullByDefault
/**
* Constructs a system service instance.
- *
+ *
* @param serviceName name of the service, such as <code>intrusionDetectionService</code>
* @param stateClass the class representing states of the system
* @param endpoint the part of the URL after <code>https://{IP}:8444/smarthome/</code>, e.g.
package org.openhab.binding.boschshc.internal.services.dto;
import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.boschshc.internal.serialization.GsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
*/
public class BoschSHCServiceState {
- /**
- * gson instance to convert a class to json string and back.
- */
- private static final Gson GSON = new Gson();
-
- /**
- * Logger marked as transient to exclude the logger from JSON serialization.
- */
- private final transient Logger logger = LoggerFactory.getLogger(BoschSHCServiceState.class);
+ private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* State type. Initialized when instance is created.
public static <TState extends BoschSHCServiceState> @Nullable TState fromJson(String json,
Class<TState> stateClass) {
- var state = GSON.fromJson(json, stateClass);
+ var state = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(json, stateClass);
if (state == null || !state.isValid()) {
return null;
}
public static <TState extends BoschSHCServiceState> @Nullable TState fromJson(JsonElement json,
Class<TState> stateClass) {
- var state = GSON.fromJson(json, stateClass);
+ var state = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(json, stateClass);
if (state == null || !state.isValid()) {
return null;
}
import javax.measure.quantity.Dimensionless;
+import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
+import org.openhab.binding.boschshc.internal.services.humiditylevel.HumidityLevelService;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units;
import org.openhab.core.types.State;
public double humidity;
public State getHumidityState() {
- return new QuantityType<Dimensionless>(this.humidity, Units.PERCENT);
+ return new QuantityType<@NonNull Dimensionless>(this.humidity, Units.PERCENT);
}
}
import javax.measure.quantity.Temperature;
+import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
+import org.openhab.binding.boschshc.internal.services.roomclimatecontrol.RoomClimateControlService;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.types.State;
/**
* State for {@link RoomClimateControlService} to get and set the desired temperature of a room.
- *
+ *
* @author Christian Oeing - Initial contribution
*/
public class RoomClimateControlServiceState extends BoschSHCServiceState {
- private static final String TYPE = "climateControlState";
+ private static final String CLIMATE_CONTROL_STATE_TYPE = "climateControlState";
public RoomClimateControlServiceState() {
- super(TYPE);
+ super(CLIMATE_CONTROL_STATE_TYPE);
}
/**
* Constructor.
- *
+ *
* @param setpointTemperature Desired temperature (in degree celsius).
*/
public RoomClimateControlServiceState(double setpointTemperature) {
- super(TYPE);
+ super(CLIMATE_CONTROL_STATE_TYPE);
this.setpointTemperature = setpointTemperature;
}
/**
* Desired temperature (in degree celsius).
- *
+ *
* @apiNote Min: 5.0, Max: 30.0.
* @apiNote Can be set in 0.5 steps.
*/
/**
* Desired temperature state to set for a thing.
- *
+ *
* @return Desired temperature state to set for a thing.
*/
public State getSetpointTemperatureState() {
- return new QuantityType<Temperature>(this.setpointTemperature, SIUnits.CELSIUS);
+ return new QuantityType<@NonNull Temperature>(this.setpointTemperature, SIUnits.CELSIUS);
}
}
/**
* Possible states for a smoke detector.
- *
+ *
* @author Christian Oeing - Initial contribution
*/
@NonNullByDefault
import javax.measure.quantity.Temperature;
+import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.boschshc.internal.services.dto.BoschSHCServiceState;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits;
/**
* TemperatureLevel service state.
- *
+ *
* @author Christian Oeing - Initial contribution
*/
public class TemperatureLevelServiceState extends BoschSHCServiceState {
/**
* Current temperature state to set for a thing.
- *
+ *
* @return Current temperature state to use for a thing.
*/
public State getTemperatureState() {
- return new QuantityType<Temperature>(this.temperature, SIUnits.CELSIUS);
+ return new QuantityType<@NonNull Temperature>(this.temperature, SIUnits.CELSIUS);
}
}
import java.util.function.BiFunction;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.http.HttpMethod;
fixture.setCallback(thingHandlerCallback);
Configuration bridgeConfiguration = new Configuration();
- Map<String, Object> properties = new HashMap<>();
+ Map<@Nullable String, @Nullable Object> properties = new HashMap<>();
properties.put("ipAddress", "localhost");
properties.put("password", "test");
bridgeConfiguration.setProperties(properties);
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
-
-import com.google.gson.Gson;
+import org.openhab.binding.boschshc.internal.serialization.GsonUtils;
/**
* Unit tests for LongPollResult
*/
@NonNullByDefault
public class LongPollResultTest {
- private final Gson gson = new Gson();
@Test
void noResultsForErrorResult() {
- LongPollResult longPollResult = gson.fromJson(
+ LongPollResult longPollResult = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(
"{\"jsonrpc\":\"2.0\", \"error\": { \"code\":-32001, \"message\":\"No subscription with id: e8fei62b0-0\" } }",
LongPollResult.class);
assertNotNull(longPollResult);
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
+import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.junit.jupiter.api.Test;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData;
import org.openhab.binding.boschshc.internal.devices.bridge.dto.Fault;
deviceServiceData.faults = faults;
assertSame(BatteryLevel.OK, BatteryLevel.fromDeviceServiceData(deviceServiceData));
- ArrayList<Fault> entries = new ArrayList<>();
+ List<@Nullable Fault> entries = new ArrayList<>();
faults.entries = entries;
assertSame(BatteryLevel.OK, BatteryLevel.fromDeviceServiceData(deviceServiceData));
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
+import org.openhab.binding.boschshc.internal.serialization.GsonUtils;
-import com.google.gson.Gson;
import com.google.gson.JsonObject;
/**
*/
@NonNullByDefault
public class BoschSHCServiceStateTest {
- private final Gson gson = new Gson();
@Test
public void fromJsonNullStateForDifferentType() {
- var state = BoschSHCServiceState.fromJson(gson.fromJson("{\"@type\":\"differentState\"}", JsonObject.class),
+ var state = BoschSHCServiceState.fromJson(
+ GsonUtils.DEFAULT_GSON_INSTANCE.fromJson("{\"@type\":\"differentState\"}", JsonObject.class),
TestState.class);
assertEquals(null, state);
}
@Test
public void fromJsonStateObjectForValidJson() {
- var state = BoschSHCServiceState.fromJson(gson.fromJson("{\"@type\":\"testState\"}", JsonObject.class),
+ var state = BoschSHCServiceState.fromJson(
+ GsonUtils.DEFAULT_GSON_INSTANCE.fromJson("{\"@type\":\"testState\"}", JsonObject.class),
TestState.class);
assertNotEquals(null, state);
}
*/
@Test
public void fromJsonStateObjectForValidJsonAfterOtherState() {
- BoschSHCServiceState.fromJson(gson.fromJson("{\"@type\":\"testState\"}", JsonObject.class), TestState.class);
- var state2 = BoschSHCServiceState.fromJson(gson.fromJson("{\"@type\":\"testState2\"}", JsonObject.class),
+ BoschSHCServiceState.fromJson(
+ GsonUtils.DEFAULT_GSON_INSTANCE.fromJson("{\"@type\":\"testState\"}", JsonObject.class),
+ TestState.class);
+ var state2 = BoschSHCServiceState.fromJson(
+ GsonUtils.DEFAULT_GSON_INSTANCE.fromJson("{\"@type\":\"testState2\"}", JsonObject.class),
TestState2.class);
assertNotEquals(null, state2);
}