mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[melcloud] Improve null handling (#17295)
* Add null annotations Signed-off-by: Leo Siepel <leosiepel@gmail.com>
This commit is contained in:
parent
27e08879f6
commit
d2d2e63016
@ -17,6 +17,7 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
@ -26,6 +27,7 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||
* @author Luca Calcaterra - Initial contribution
|
||||
* @author Wietse van Buitenen - Added heatpump device
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MelCloudBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = "melcloud";
|
||||
|
@ -14,6 +14,7 @@ package org.openhab.binding.melcloud.internal;
|
||||
|
||||
import static org.openhab.binding.melcloud.internal.MelCloudBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.melcloud.internal.handler.MelCloudAccountHandler;
|
||||
import org.openhab.binding.melcloud.internal.handler.MelCloudDeviceHandler;
|
||||
@ -33,6 +34,7 @@ import org.osgi.service.component.annotations.Component;
|
||||
* @author Luca Calcaterra - Initial contribution
|
||||
* @author Wietse van Buitenen - Added heatpump device
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.melcloud", service = ThingHandlerFactory.class)
|
||||
public class MelCloudHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
|
@ -19,13 +19,15 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.openhab.binding.melcloud.internal.api.json.Device;
|
||||
import org.openhab.binding.melcloud.internal.api.json.DeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.api.json.HeatpumpDeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.api.json.ListDevicesResponse;
|
||||
import org.openhab.binding.melcloud.internal.api.json.LoginClientResponse;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.Device;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.DeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.HeatpumpDeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.ListDevicesResponse;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.LoginClientResponse;
|
||||
import org.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
|
||||
import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
@ -45,6 +47,7 @@ import com.google.gson.JsonSyntaxException;
|
||||
* @author Pauli Anttila - Refactoring
|
||||
* @author Wietse van Buitenen - Return all devices, added heatpump device
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MelCloudConnection {
|
||||
|
||||
private static final String LOGIN_URL = "https://app.melcloud.com/Mitsubishi.Wifi.Client/Login/ClientLogin";
|
||||
@ -54,18 +57,18 @@ public class MelCloudConnection {
|
||||
private static final int TIMEOUT_MILLISECONDS = 10000;
|
||||
|
||||
// Gson objects are safe to share across threads and are somewhat expensive to construct. Use a single instance.
|
||||
private static final Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
|
||||
private static final Gson GSON = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
|
||||
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MelCloudConnection.class);
|
||||
|
||||
private boolean isConnected = false;
|
||||
private String sessionKey;
|
||||
private String sessionKey = "";
|
||||
|
||||
public void login(String username, String password, int languageId)
|
||||
throws MelCloudCommException, MelCloudLoginException {
|
||||
setConnected(false);
|
||||
sessionKey = null;
|
||||
sessionKey = "";
|
||||
JsonObject jsonReq = new JsonObject();
|
||||
jsonReq.addProperty("Email", username);
|
||||
jsonReq.addProperty("Password", password);
|
||||
@ -79,7 +82,7 @@ public class MelCloudConnection {
|
||||
String loginResponse = HttpUtil.executeUrl("POST", LOGIN_URL, null, data, "application/json",
|
||||
TIMEOUT_MILLISECONDS);
|
||||
logger.debug("Login response: {}", loginResponse);
|
||||
LoginClientResponse resp = gson.fromJson(loginResponse, LoginClientResponse.class);
|
||||
LoginClientResponse resp = Objects.requireNonNull(GSON.fromJson(loginResponse, LoginClientResponse.class));
|
||||
if (resp.getErrorId() != null) {
|
||||
String errorMsg = String.format("Login failed, error code: %s", resp.getErrorId());
|
||||
if (resp.getErrorMessage() != null) {
|
||||
@ -101,7 +104,7 @@ public class MelCloudConnection {
|
||||
TIMEOUT_MILLISECONDS);
|
||||
logger.debug("Device list response: {}", response);
|
||||
List<Device> devices = new ArrayList<>();
|
||||
ListDevicesResponse[] buildings = gson.fromJson(response, ListDevicesResponse[].class);
|
||||
ListDevicesResponse[] buildings = GSON.fromJson(response, ListDevicesResponse[].class);
|
||||
Arrays.asList(buildings).forEach(building -> {
|
||||
if (building.getStructure().getDevices() != null) {
|
||||
devices.addAll(building.getStructure().getDevices());
|
||||
@ -137,7 +140,7 @@ public class MelCloudConnection {
|
||||
try {
|
||||
String response = HttpUtil.executeUrl("GET", url, getHeaderProperties(), null, null, TIMEOUT_MILLISECONDS);
|
||||
logger.debug("Device status response: {}", response);
|
||||
return gson.fromJson(response, DeviceStatus.class);
|
||||
return Objects.requireNonNull(GSON.fromJson(response, DeviceStatus.class));
|
||||
} catch (IOException | JsonSyntaxException e) {
|
||||
setConnected(false);
|
||||
throw new MelCloudCommException("Error occurred during device status fetch", e);
|
||||
@ -146,14 +149,14 @@ public class MelCloudConnection {
|
||||
|
||||
public DeviceStatus sendDeviceStatus(DeviceStatus deviceStatus) throws MelCloudCommException {
|
||||
assertConnected();
|
||||
String content = gson.toJson(deviceStatus, DeviceStatus.class);
|
||||
String content = GSON.toJson(deviceStatus, DeviceStatus.class);
|
||||
logger.debug("Sending device status: {}", content);
|
||||
InputStream data = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
|
||||
try {
|
||||
String response = HttpUtil.executeUrl("POST", DEVICE_URL + "/SetAta", getHeaderProperties(), data,
|
||||
"application/json", TIMEOUT_MILLISECONDS);
|
||||
logger.debug("Device status sending response: {}", response);
|
||||
return gson.fromJson(response, DeviceStatus.class);
|
||||
return Objects.requireNonNull(GSON.fromJson(response, DeviceStatus.class));
|
||||
} catch (IOException | JsonSyntaxException e) {
|
||||
setConnected(false);
|
||||
throw new MelCloudCommException("Error occurred during device command sending", e);
|
||||
@ -166,7 +169,7 @@ public class MelCloudConnection {
|
||||
try {
|
||||
String response = HttpUtil.executeUrl("GET", url, getHeaderProperties(), null, null, TIMEOUT_MILLISECONDS);
|
||||
logger.debug("Device heatpump status response: {}", response);
|
||||
return gson.fromJson(response, HeatpumpDeviceStatus.class);
|
||||
return Objects.requireNonNull(GSON.fromJson(response, HeatpumpDeviceStatus.class));
|
||||
} catch (IOException | JsonSyntaxException e) {
|
||||
setConnected(false);
|
||||
throw new MelCloudCommException("Error occurred during heatpump device status fetch", e);
|
||||
@ -176,14 +179,14 @@ public class MelCloudConnection {
|
||||
public HeatpumpDeviceStatus sendHeatpumpDeviceStatus(HeatpumpDeviceStatus heatpumpDeviceStatus)
|
||||
throws MelCloudCommException {
|
||||
assertConnected();
|
||||
String content = gson.toJson(heatpumpDeviceStatus, HeatpumpDeviceStatus.class);
|
||||
String content = GSON.toJson(heatpumpDeviceStatus, HeatpumpDeviceStatus.class);
|
||||
logger.debug("Sending heatpump device status: {}", content);
|
||||
InputStream data = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
|
||||
try {
|
||||
String response = HttpUtil.executeUrl("POST", DEVICE_URL + "/SetAtw", getHeaderProperties(), data,
|
||||
"application/json", TIMEOUT_MILLISECONDS);
|
||||
logger.debug("Device heatpump status sending response: {}", response);
|
||||
return gson.fromJson(response, HeatpumpDeviceStatus.class);
|
||||
return Objects.requireNonNull(GSON.fromJson(response, HeatpumpDeviceStatus.class));
|
||||
} catch (IOException | JsonSyntaxException e) {
|
||||
setConnected(false);
|
||||
throw new MelCloudCommException("Error occurred during heatpump device command sending", e);
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import java.security.Permissions;
|
||||
import java.util.List;
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.api.json;
|
||||
package org.openhab.binding.melcloud.internal.api.dto;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
|
@ -12,17 +12,21 @@
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Config class for an A.C. device.
|
||||
*
|
||||
* @author Pauli Anttila - Initial Contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AcDeviceConfig {
|
||||
|
||||
public Integer deviceID;
|
||||
public Integer buildingID;
|
||||
public Integer pollingInterval;
|
||||
public Integer deviceID = 0;
|
||||
public @Nullable Integer buildingID;
|
||||
public Integer pollingInterval = 360;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -12,17 +12,20 @@
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Config class for MELCloud account parameters.
|
||||
*
|
||||
* @author Pauli Anttila - Initial Contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AccountConfig {
|
||||
|
||||
public String username;
|
||||
public String password;
|
||||
public int language;
|
||||
public String username = "";
|
||||
public String password = "";
|
||||
public int language = 0;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@ -30,9 +33,6 @@ public class AccountConfig {
|
||||
}
|
||||
|
||||
private String getPasswordForPrinting() {
|
||||
if (password != null) {
|
||||
return password.isEmpty() ? "<empty>" : "*********";
|
||||
}
|
||||
return "<null>";
|
||||
return password.isEmpty() ? "<empty>" : "*********";
|
||||
}
|
||||
}
|
||||
|
@ -12,16 +12,20 @@
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Config class for a Heatpump device.
|
||||
*
|
||||
* @author Wietse van Buitenen - Initial Contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HeatpumpDeviceConfig {
|
||||
public Integer deviceID;
|
||||
public Integer buildingID;
|
||||
public Integer pollingInterval;
|
||||
public Integer deviceID = 0;
|
||||
public @Nullable Integer buildingID;
|
||||
public Integer pollingInterval = 360;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -20,9 +20,10 @@ import java.util.Map;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.melcloud.internal.MelCloudBindingConstants;
|
||||
import org.openhab.binding.melcloud.internal.api.json.Device;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.Device;
|
||||
import org.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
|
||||
import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
|
||||
import org.openhab.binding.melcloud.internal.handler.MelCloudAccountHandler;
|
||||
@ -43,14 +44,15 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Pauli Anttila - Refactoring
|
||||
* @author Wietse van Buitenen - Check device type, added heatpump device
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(scope = ServiceScope.PROTOTYPE, service = MelCloudDiscoveryService.class)
|
||||
public class MelCloudDiscoveryService extends AbstractThingHandlerDiscoveryService<@NonNull MelCloudAccountHandler> {
|
||||
public class MelCloudDiscoveryService extends AbstractThingHandlerDiscoveryService<MelCloudAccountHandler> {
|
||||
private final Logger logger = LoggerFactory.getLogger(MelCloudDiscoveryService.class);
|
||||
|
||||
private static final String PROPERTY_DEVICE_ID = "deviceID";
|
||||
private static final int DISCOVER_TIMEOUT_SECONDS = 10;
|
||||
|
||||
private ScheduledFuture<?> scanTask;
|
||||
private @Nullable ScheduledFuture<?> scanTask;
|
||||
|
||||
/**
|
||||
* Creates a MelCloudDiscoveryService with enabled autostart.
|
||||
@ -67,7 +69,8 @@ public class MelCloudDiscoveryService extends AbstractThingHandlerDiscoveryServi
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
if (this.scanTask != null) {
|
||||
ScheduledFuture<?> scanTask = this.scanTask;
|
||||
if (scanTask != null) {
|
||||
scanTask.cancel(true);
|
||||
}
|
||||
this.scanTask = scheduler.schedule(() -> discoverDevices(), 0, TimeUnit.SECONDS);
|
||||
@ -77,8 +80,9 @@ public class MelCloudDiscoveryService extends AbstractThingHandlerDiscoveryServi
|
||||
protected void stopScan() {
|
||||
super.stopScan();
|
||||
|
||||
if (this.scanTask != null) {
|
||||
this.scanTask.cancel(true);
|
||||
ScheduledFuture<?> scanTask = this.scanTask;
|
||||
if (scanTask != null) {
|
||||
scanTask.cancel(true);
|
||||
this.scanTask = null;
|
||||
}
|
||||
}
|
||||
@ -88,7 +92,7 @@ public class MelCloudDiscoveryService extends AbstractThingHandlerDiscoveryServi
|
||||
try {
|
||||
List<Device> deviceList = thingHandler.getDeviceList();
|
||||
|
||||
if (deviceList == null) {
|
||||
if (deviceList.isEmpty()) {
|
||||
logger.debug("No devices found");
|
||||
} else {
|
||||
ThingUID bridgeUID = thingHandler.getThing().getUID();
|
||||
|
@ -12,11 +12,14 @@
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.exceptions;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Exception to encapsulate any issues communicating with MELCloud.
|
||||
*
|
||||
* @author Pauli Anttila - Initial Contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MelCloudCommException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
@ -12,11 +12,14 @@
|
||||
*/
|
||||
package org.openhab.binding.melcloud.internal.exceptions;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Exception to encapsulate any login issues with MELCloud.
|
||||
*
|
||||
* @author Pauli Anttila - Initial Contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MelCloudLoginException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
@ -15,15 +15,16 @@ package org.openhab.binding.melcloud.internal.handler;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.melcloud.internal.api.MelCloudConnection;
|
||||
import org.openhab.binding.melcloud.internal.api.json.Device;
|
||||
import org.openhab.binding.melcloud.internal.api.json.DeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.api.json.HeatpumpDeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.Device;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.DeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.HeatpumpDeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.config.AccountConfig;
|
||||
import org.openhab.binding.melcloud.internal.discovery.MelCloudDiscoveryService;
|
||||
import org.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
|
||||
@ -47,14 +48,15 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Pauli Anttila - Refactoring
|
||||
* @author Wietse van Buitenen - Return all devices, added heatpump device
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MelCloudAccountHandler extends BaseBridgeHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(MelCloudAccountHandler.class);
|
||||
|
||||
private MelCloudConnection connection;
|
||||
private List<Device> devices;
|
||||
private ScheduledFuture<?> connectionCheckTask;
|
||||
private AccountConfig config;
|
||||
private boolean loginCredentialError;
|
||||
private MelCloudConnection connection = new MelCloudConnection();
|
||||
private List<Device> devices = Collections.emptyList();
|
||||
private @Nullable ScheduledFuture<?> connectionCheckTask;
|
||||
private AccountConfig config = new AccountConfig();
|
||||
private boolean loginCredentialError = false;
|
||||
|
||||
public MelCloudAccountHandler(Bridge bridge) {
|
||||
super(bridge);
|
||||
@ -69,8 +71,6 @@ public class MelCloudAccountHandler extends BaseBridgeHandler {
|
||||
public void initialize() {
|
||||
logger.debug("Initializing MELCloud account handler.");
|
||||
config = getConfigAs(AccountConfig.class);
|
||||
connection = new MelCloudConnection();
|
||||
devices = Collections.emptyList();
|
||||
loginCredentialError = false;
|
||||
startConnectionCheck();
|
||||
}
|
||||
@ -79,9 +79,7 @@ public class MelCloudAccountHandler extends BaseBridgeHandler {
|
||||
public void dispose() {
|
||||
logger.debug("Running dispose()");
|
||||
stopConnectionCheck();
|
||||
connection = null;
|
||||
devices = Collections.emptyList();
|
||||
config = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -102,6 +100,7 @@ public class MelCloudAccountHandler extends BaseBridgeHandler {
|
||||
throw new MelCloudLoginException("Connection to MELCloud can't be opened because of wrong credentials");
|
||||
}
|
||||
logger.debug("Initializing connection to MELCloud");
|
||||
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
try {
|
||||
connection.login(config.username, config.password, config.language);
|
||||
@ -139,10 +138,10 @@ public class MelCloudAccountHandler extends BaseBridgeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public DeviceStatus fetchDeviceStatus(int deviceId, Optional<Integer> buildingId)
|
||||
public DeviceStatus fetchDeviceStatus(int deviceId, @Nullable Integer buildingId)
|
||||
throws MelCloudCommException, MelCloudLoginException {
|
||||
connectIfNotConnected();
|
||||
int bid = buildingId.orElse(findBuildingId(deviceId));
|
||||
int bid = buildingId != null ? buildingId : findBuildingId(deviceId);
|
||||
|
||||
try {
|
||||
return connection.fetchDeviceStatus(deviceId, bid);
|
||||
@ -165,10 +164,10 @@ public class MelCloudAccountHandler extends BaseBridgeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public HeatpumpDeviceStatus fetchHeatpumpDeviceStatus(int deviceId, Optional<Integer> buildingId)
|
||||
public HeatpumpDeviceStatus fetchHeatpumpDeviceStatus(int deviceId, @Nullable Integer buildingId)
|
||||
throws MelCloudCommException, MelCloudLoginException {
|
||||
connectIfNotConnected();
|
||||
int bid = buildingId.orElse(findBuildingId(deviceId));
|
||||
int bid = buildingId != null ? buildingId : findBuildingId(deviceId);
|
||||
|
||||
try {
|
||||
return connection.fetchHeatpumpDeviceStatus(deviceId, bid);
|
||||
@ -180,15 +179,13 @@ public class MelCloudAccountHandler extends BaseBridgeHandler {
|
||||
}
|
||||
|
||||
private int findBuildingId(int deviceId) throws MelCloudCommException {
|
||||
if (devices != null) {
|
||||
return devices.stream().filter(d -> d.getDeviceID() == deviceId).findFirst().orElseThrow(
|
||||
() -> new MelCloudCommException(String.format("Can't find building id for device id %s", deviceId)))
|
||||
.getBuildingID();
|
||||
}
|
||||
throw new MelCloudCommException(String.format("Can't find building id for device id %s", deviceId));
|
||||
return devices.stream().filter(d -> d.getDeviceID() == deviceId).findFirst().orElseThrow(
|
||||
() -> new MelCloudCommException(String.format("Can't find building id for device id %s", deviceId)))
|
||||
.getBuildingID();
|
||||
}
|
||||
|
||||
private void startConnectionCheck() {
|
||||
ScheduledFuture<?> connectionCheckTask = this.connectionCheckTask;
|
||||
if (connectionCheckTask == null || connectionCheckTask.isCancelled()) {
|
||||
logger.debug("Start periodic connection check");
|
||||
Runnable runnable = () -> {
|
||||
@ -207,17 +204,18 @@ public class MelCloudAccountHandler extends BaseBridgeHandler {
|
||||
}
|
||||
}
|
||||
};
|
||||
connectionCheckTask = scheduler.scheduleWithFixedDelay(runnable, 0, 300, TimeUnit.SECONDS);
|
||||
this.connectionCheckTask = scheduler.scheduleWithFixedDelay(runnable, 0, 300, TimeUnit.SECONDS);
|
||||
} else {
|
||||
logger.debug("Connection check task already running");
|
||||
}
|
||||
}
|
||||
|
||||
private void stopConnectionCheck() {
|
||||
ScheduledFuture<?> connectionCheckTask = this.connectionCheckTask;
|
||||
if (connectionCheckTask != null) {
|
||||
logger.debug("Stop periodic connection check");
|
||||
connectionCheckTask.cancel(true);
|
||||
connectionCheckTask = null;
|
||||
this.connectionCheckTask = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,13 +22,14 @@ import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.openhab.binding.melcloud.internal.api.json.DeviceStatus;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.DeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.config.AcDeviceConfig;
|
||||
import org.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
|
||||
import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
|
||||
@ -46,6 +47,7 @@ import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.BridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
@ -59,7 +61,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Luca Calcaterra - Initial contribution
|
||||
* @author Pauli Anttila - Refactoring
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class MelCloudDeviceHandler extends BaseThingHandler {
|
||||
|
||||
private static final int EFFECTIVE_FLAG_POWER = 0x01;
|
||||
@ -70,10 +72,10 @@ public class MelCloudDeviceHandler extends BaseThingHandler {
|
||||
private static final int EFFECTIVE_FLAG_VANE_HORIZONTAL = 0x100;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MelCloudDeviceHandler.class);
|
||||
private AcDeviceConfig config;
|
||||
private MelCloudAccountHandler melCloudHandler;
|
||||
private DeviceStatus deviceStatus;
|
||||
private ScheduledFuture<?> refreshTask;
|
||||
private AcDeviceConfig config = new AcDeviceConfig();
|
||||
private @Nullable MelCloudAccountHandler melCloudHandler;
|
||||
private @Nullable DeviceStatus deviceStatus;
|
||||
private @Nullable ScheduledFuture<?> refreshTask;
|
||||
|
||||
public MelCloudDeviceHandler(Thing thing) {
|
||||
super(thing);
|
||||
@ -84,7 +86,7 @@ public class MelCloudDeviceHandler extends BaseThingHandler {
|
||||
logger.debug("Initializing {} handler.", getThing().getThingTypeUID());
|
||||
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
if (bridge == null || !(bridge.getHandler() instanceof BridgeHandler bridgeHandler)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge Not set");
|
||||
return;
|
||||
}
|
||||
@ -92,15 +94,16 @@ public class MelCloudDeviceHandler extends BaseThingHandler {
|
||||
config = getConfigAs(AcDeviceConfig.class);
|
||||
logger.debug("A.C. device config: {}", config);
|
||||
|
||||
initializeBridge(bridge.getHandler(), bridge.getStatus());
|
||||
initializeBridge(bridgeHandler, bridge.getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Running dispose()");
|
||||
ScheduledFuture<?> refreshTask = this.refreshTask;
|
||||
if (refreshTask != null) {
|
||||
refreshTask.cancel(true);
|
||||
refreshTask = null;
|
||||
this.refreshTask = null;
|
||||
}
|
||||
melCloudHandler = null;
|
||||
}
|
||||
@ -109,25 +112,21 @@ public class MelCloudDeviceHandler extends BaseThingHandler {
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
logger.debug("bridgeStatusChanged {} for thing {}", bridgeStatusInfo, getThing().getUID());
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
initializeBridge(bridge.getHandler(), bridgeStatusInfo.getStatus());
|
||||
if (bridge != null && bridge.getHandler() instanceof BridgeHandler bridgeHandler) {
|
||||
initializeBridge(bridgeHandler, bridgeStatusInfo.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeBridge(ThingHandler thingHandler, ThingStatus bridgeStatus) {
|
||||
logger.debug("initializeBridge {} for thing {}", bridgeStatus, getThing().getUID());
|
||||
|
||||
if (thingHandler != null && bridgeStatus != null) {
|
||||
melCloudHandler = (MelCloudAccountHandler) thingHandler;
|
||||
melCloudHandler = (MelCloudAccountHandler) thingHandler;
|
||||
|
||||
if (bridgeStatus == ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
startAutomaticRefresh();
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
if (bridgeStatus == ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
startAutomaticRefresh();
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,12 +138,12 @@ public class MelCloudDeviceHandler extends BaseThingHandler {
|
||||
logger.debug("Refresh command not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
MelCloudAccountHandler melCloudHandler = this.melCloudHandler;
|
||||
if (melCloudHandler == null) {
|
||||
logger.warn("No connection to MELCloud available, ignoring command");
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceStatus deviceStatus = this.deviceStatus;
|
||||
if (deviceStatus == null) {
|
||||
logger.info("No initial data available, bridge is probably offline. Ignoring command");
|
||||
return;
|
||||
@ -229,18 +228,19 @@ public class MelCloudDeviceHandler extends BaseThingHandler {
|
||||
}
|
||||
|
||||
private void startAutomaticRefresh() {
|
||||
ScheduledFuture<?> refreshTask = this.refreshTask;
|
||||
if (refreshTask == null || refreshTask.isCancelled()) {
|
||||
refreshTask = scheduler.scheduleWithFixedDelay(this::getDeviceDataAndUpdateChannels, 1,
|
||||
this.refreshTask = scheduler.scheduleWithFixedDelay(this::getDeviceDataAndUpdateChannels, 1,
|
||||
config.pollingInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private void getDeviceDataAndUpdateChannels() {
|
||||
if (melCloudHandler.isConnected()) {
|
||||
MelCloudAccountHandler melCloudHandler = this.melCloudHandler;
|
||||
if (melCloudHandler != null && melCloudHandler.isConnected()) {
|
||||
logger.debug("Update device '{}' channels", getThing().getThingTypeUID());
|
||||
try {
|
||||
DeviceStatus newDeviceStatus = melCloudHandler.fetchDeviceStatus(config.deviceID,
|
||||
Optional.ofNullable(config.buildingID));
|
||||
DeviceStatus newDeviceStatus = melCloudHandler.fetchDeviceStatus(config.deviceID, config.buildingID);
|
||||
updateChannels(newDeviceStatus);
|
||||
} catch (MelCloudLoginException e) {
|
||||
logger.debug("Login error occurred during device '{}' polling, reason {}. ",
|
||||
@ -255,7 +255,7 @@ public class MelCloudDeviceHandler extends BaseThingHandler {
|
||||
}
|
||||
|
||||
private synchronized void updateChannels(DeviceStatus newDeviceStatus) {
|
||||
deviceStatus = newDeviceStatus;
|
||||
DeviceStatus deviceStatus = this.deviceStatus = newDeviceStatus;
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
updateChannels(channel.getUID().getId(), deviceStatus);
|
||||
}
|
||||
|
@ -22,13 +22,14 @@ import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.openhab.binding.melcloud.internal.api.json.HeatpumpDeviceStatus;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.melcloud.internal.api.dto.HeatpumpDeviceStatus;
|
||||
import org.openhab.binding.melcloud.internal.config.HeatpumpDeviceConfig;
|
||||
import org.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
|
||||
import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
|
||||
@ -45,6 +46,7 @@ import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.BridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
@ -57,16 +59,17 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Wietse van Buitenen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MelCloudHeatpumpDeviceHandler extends BaseThingHandler {
|
||||
private static final long EFFECTIVE_FLAG_POWER = 1L;
|
||||
private static final long EFFECTIVE_FLAG_TEMPERATURE_ZONE1 = 8589934720L;
|
||||
private static final long EFFECTIVE_FLAG_HOTWATER = 65536L;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MelCloudHeatpumpDeviceHandler.class);
|
||||
private HeatpumpDeviceConfig config;
|
||||
private MelCloudAccountHandler melCloudHandler;
|
||||
private HeatpumpDeviceStatus heatpumpDeviceStatus;
|
||||
private ScheduledFuture<?> refreshTask;
|
||||
private HeatpumpDeviceConfig config = new HeatpumpDeviceConfig();
|
||||
private @Nullable MelCloudAccountHandler melCloudHandler;
|
||||
private @Nullable HeatpumpDeviceStatus heatpumpDeviceStatus;
|
||||
private @Nullable ScheduledFuture<?> refreshTask;
|
||||
|
||||
public MelCloudHeatpumpDeviceHandler(Thing thing) {
|
||||
super(thing);
|
||||
@ -77,7 +80,7 @@ public class MelCloudHeatpumpDeviceHandler extends BaseThingHandler {
|
||||
logger.debug("Initializing {} handler.", getThing().getThingTypeUID());
|
||||
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
if (bridge == null || !(bridge.getHandler() instanceof BridgeHandler bridgeHandler)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge Not set");
|
||||
return;
|
||||
}
|
||||
@ -85,15 +88,16 @@ public class MelCloudHeatpumpDeviceHandler extends BaseThingHandler {
|
||||
config = getConfigAs(HeatpumpDeviceConfig.class);
|
||||
logger.debug("Heatpump device config: {}", config);
|
||||
|
||||
initializeBridge(bridge.getHandler(), bridge.getStatus());
|
||||
initializeBridge(bridgeHandler, bridge.getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Running dispose()");
|
||||
ScheduledFuture<?> refreshTask = this.refreshTask;
|
||||
if (refreshTask != null) {
|
||||
refreshTask.cancel(true);
|
||||
refreshTask = null;
|
||||
this.refreshTask = null;
|
||||
}
|
||||
melCloudHandler = null;
|
||||
}
|
||||
@ -102,25 +106,21 @@ public class MelCloudHeatpumpDeviceHandler extends BaseThingHandler {
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
logger.debug("bridgeStatusChanged {} for thing {}", bridgeStatusInfo, getThing().getUID());
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
initializeBridge(bridge.getHandler(), bridgeStatusInfo.getStatus());
|
||||
if (bridge != null && bridge.getHandler() instanceof BridgeHandler bridgeHandler) {
|
||||
initializeBridge(bridgeHandler, bridgeStatusInfo.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeBridge(ThingHandler thingHandler, ThingStatus bridgeStatus) {
|
||||
logger.debug("initializeBridge {} for thing {}", bridgeStatus, getThing().getUID());
|
||||
|
||||
if (thingHandler != null && bridgeStatus != null) {
|
||||
melCloudHandler = (MelCloudAccountHandler) thingHandler;
|
||||
melCloudHandler = (MelCloudAccountHandler) thingHandler;
|
||||
|
||||
if (bridgeStatus == ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
startAutomaticRefresh();
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
if (bridgeStatus == ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
startAutomaticRefresh();
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,11 +133,12 @@ public class MelCloudHeatpumpDeviceHandler extends BaseThingHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
MelCloudAccountHandler melCloudHandler = this.melCloudHandler;
|
||||
if (melCloudHandler == null) {
|
||||
logger.warn("No connection to MELCloud available, ignoring command");
|
||||
return;
|
||||
}
|
||||
|
||||
HeatpumpDeviceStatus heatpumpDeviceStatus = this.heatpumpDeviceStatus;
|
||||
if (heatpumpDeviceStatus == null) {
|
||||
logger.info("No initial data available, bridge is probably offline. Ignoring command");
|
||||
return;
|
||||
@ -207,18 +208,20 @@ public class MelCloudHeatpumpDeviceHandler extends BaseThingHandler {
|
||||
}
|
||||
|
||||
private void startAutomaticRefresh() {
|
||||
ScheduledFuture<?> refreshTask = this.refreshTask;
|
||||
if (refreshTask == null || refreshTask.isCancelled()) {
|
||||
refreshTask = scheduler.scheduleWithFixedDelay(this::getDeviceDataAndUpdateChannels, 1,
|
||||
this.refreshTask = scheduler.scheduleWithFixedDelay(this::getDeviceDataAndUpdateChannels, 1,
|
||||
config.pollingInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private void getDeviceDataAndUpdateChannels() {
|
||||
if (melCloudHandler.isConnected()) {
|
||||
MelCloudAccountHandler melCloudHandler = this.melCloudHandler;
|
||||
if (melCloudHandler != null && melCloudHandler.isConnected()) {
|
||||
logger.debug("Update device '{}' channels", getThing().getThingTypeUID());
|
||||
try {
|
||||
HeatpumpDeviceStatus newHeatpumpDeviceStatus = melCloudHandler
|
||||
.fetchHeatpumpDeviceStatus(config.deviceID, Optional.ofNullable(config.buildingID));
|
||||
.fetchHeatpumpDeviceStatus(config.deviceID, config.buildingID);
|
||||
updateChannels(newHeatpumpDeviceStatus);
|
||||
} catch (MelCloudLoginException e) {
|
||||
logger.debug("Login error occurred during device '{}' polling, reason {}. ",
|
||||
@ -233,7 +236,7 @@ public class MelCloudHeatpumpDeviceHandler extends BaseThingHandler {
|
||||
}
|
||||
|
||||
private synchronized void updateChannels(HeatpumpDeviceStatus newHeatpumpDeviceStatus) {
|
||||
heatpumpDeviceStatus = newHeatpumpDeviceStatus;
|
||||
HeatpumpDeviceStatus heatpumpDeviceStatus = this.heatpumpDeviceStatus = newHeatpumpDeviceStatus;
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
updateChannels(channel.getUID().getId(), heatpumpDeviceStatus);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user