added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.binding.melcloud</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,13 @@
This content is produced and maintained by the openHAB project.
* Project home: https://www.openhab.org
== Declared Project Licenses
This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.
== Source Code
https://github.com/openhab/openhab-addons

View File

@@ -0,0 +1,148 @@
# MELCloud Binding
This is an openHAB binding for Mitsubishi MELCloud (https://www.melcloud.com/).
Installing this binding you can control your Mitsubishi devices from openHAB without accessing the MELCloud App and benefiting from all openHAB automations.
## Supported Things
Supported thing types
* melcloudaccount (bridge)
* acdevice
* heatpump
A bridge is required to connect to your MELCloud account.
## Discovery
Discovery is used _after_ a bridge has been created and configured with your login information.
1. Add the binding
2. Add a new thing of type melcloudaccount and configure with username and password
3. Go to Inbox and start discovery devices using MELCloud Binding
4. Supported devices (A.C. Device, Heatpump Device) should appear in your inbox
Binding support also manual thing configuration by thing files.
## Thing Configuration
In order to manually create a thing file and not use the discovery routine you will need to know device MELCloud device ID.
This is a bit difficult to get. The easiest way of getting this is enable debug level logging of the binding or discovery devices by the binding (discovered device can be removed afterwards).
MELCloud account configuration:
| Config | Mandatory | Description |
|----------|-----------|-----------------------------------------|
| username | x | Email address tied to MELCloud account. |
| password | x | Password to MELCloud account. |
| language | | Language ID, see table below. |
| LanguageId | Language |
|-------------|-------------------|
| 0 | English (default) |
| 1 | Bulgarian |
| 2 | Czech |
| 3 | Danish |
| 4 | German |
| 5 | Estonian |
| 6 | Spanish |
| 7 | French |
| 8 | Armenian |
| 9 | Latvian |
| 10 | Lithuanian |
| 11 | Hungarian |
| 12 | Dutch |
| 13 | Norwegian |
| 14 | Polish |
| 15 | Portuguese |
| 16 | Russian |
| 17 | Finnish |
| 18 | Swedish |
| 19 | Italian |
| 20 | Ukrainian |
| 21 | Turkish |
| 22 | Greek |
| 23 | Croatian |
| 24 | Romanian |
| 25 | Slovenian |
A.C. device and Heatpump device configuration:
| Config | Mandatory | Description |
|-----------------|-----------|---------------------------------------------------------------------------------------|
| deviceID | x | MELCloud device ID. |
| buildingID | | MELCloud building ID. If not defined, binding tries to find matching id by device ID. |
| pollingInterval | | Refresh time interval in seconds for updates from MELCloud. Defaults to 60 seconds. |
## Channels
A.C. device channels
| Channel | Type | Description | Read Only |
|---------------------|--------------------|------------------------------------------------------------------------------------------|-----------|
| power | Switch | Power Status of Device. | False |
| operationMode | String | Operation mode: "1" = Heat, "2" = Dry, "3" = Cool, "7" = Fan, "8" = Auto. | False |
| setTemperature | Number:Temperature | Set Temperature: Min = 10, Max = 40. | False |
| fanSpeed | String | Fan speed: "0" = Auto, "1" = 1, "2" = 2, "3" = 3, "4" = 4, "5" = 5. | False |
| vaneHorizontal | String | Vane Horizontal: "0" = Auto, "1" = 1, "2" = 2, "3" = 3, "4" = 4, "5" = 5, "12" = Swing. | False |
| vaneVertical | String | Vane Vertical: "0" = Auto, "1" = 1, "2" = 2, "3" = 3, "4" = 4, "5" = 5, "7" = Swing. | False |
| roomTemperature | Number:Temperature | Room temperature. | True |
| lastCommunication | DateTime | Last Communication time when MELCloud communicated to the device. | True |
| nextCommunication | DateTime | Next communication time when MELCloud will communicate to the device. | True |
| offline | Switch | Is device in offline state. | True |
| hasPendingCommand | Switch | Device has a pending command(s). | True |
Heatpump device channels
| Channel | Type | Description | Read Only |
|---------------------|--------------------|----------------------------------------------------------------------------|-----------|
| power | Switch | Power Status of Device. | False |
| forcedHotWaterMode | Switch | If water mode is Heat Now (true) or Auto (false) | False |
| setTemperatureZone1 | Number:Temperature | Set Temperature Zone 1: Min = 10, Max = 30. | False |
| roomTemperatureZone1| Number:Temperature | Room temperature Zone 1. | True |
| tankWaterTemperature| Number:Temperature | Tank water temperature. | True |
| lastCommunication | DateTime | Last Communication time when MELCloud communicated to the device. | True |
| nextCommunication | DateTime | Next communication time when MELCloud will communicate to the device. | True |
| offline | Switch | Is device in offline state. | True |
| hasPendingCommand | Switch | Device has a pending command(s). | True |
## Full Example for items configuration
**melcloud.things**
```
Bridge melcloud:melcloudaccount:myaccount "My MELCloud account" [ username="user.name@example.com", password="xxxxxx", language="0" ] {
Thing acdevice livingroom "Livingroom A.C. device" [ deviceID=123456, pollingInterval=60 ]
Thing heatpump attic "Attic Heatpump device" [ deviceID=789012, pollingInterval=60 ]
}
```
**melcloud.items**
```
Switch power { channel="melcloud:acdevice:myaccount:livingroom:power" }
String operationMode { channel="melcloud:acdevice:myaccount:livingroom:operationMode" }
Number setTemperature { channel="melcloud:acdevice:myaccount:livingroom:setTemperature" }
String fanSpeed { channel="melcloud:acdevice:myaccount:livingroom:fanSpeed" }
String vaneHorizontal { channel="melcloud:acdevice:myaccount:livingroom:vaneHorizontal" }
String vaneVertical { channel="melcloud:acdevice:myaccount:livingroom:vaneVertical" }
Number roomTemperature { channel="melcloud:acdevice:myaccount:livingroom:roomTemperature" }
DateTime lastCommunication { channel="melcloud:acdevice:myaccount:livingroom:lastCommunication" }
DateTime nextCommunication { channel="melcloud:acdevice:myaccount:livingroom:nextCommunication" }
Switch offline { channel="melcloud:acdevice:myaccount:livingroom:offline" }
Switch hasPendingCommand { channel="melcloud:acdevice:myaccount:livingroom:hasPendingCommand" }
Switch heatpumpPower { channel="melcloud:heatpump:myaccount:attic:power" }
Switch heatpumpForcedHotWaterMode { channel="melcloud:heatpump:myaccount:attic:forcedHotWaterMode" }
Number heatpumpSetTemperatureZone1 { channel="melcloud:heatpump:myaccount:attic:setTemperatureZone1" }
Number heatpumpRoomTemperatureZone1{ channel="melcloud:heatpump:myaccount:attic:roomTemperatureZone1" }
Number heatpumpTankWaterTemperature{ channel="melcloud:heatpump:myaccount:attic:tankWaterTemperature" }
DateTime heatpumpLastCommunication { channel="melcloud:heatpump:myaccount:attic:lastCommunication" }
DateTime heatpumpNextCommunication { channel="melcloud:heatpump:myaccount:attic:nextCommunication" }
Switch heatpumpOffline { channel="melcloud:heatpump:myaccount:attic:offline" }
Switch heatpumpHasPendingCommand { channel="melcloud:heatpump:myaccount:attic:hasPendingCommand" }
```

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.binding.melcloud</artifactId>
<name>openHAB Add-ons :: Bundles :: MELCloud Binding</name>
</project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.ihc-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-binding-melcloud" description="MELCloud Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.melcloud/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,65 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link MelCloudBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Luca Calcaterra - Initial contribution
* @author Wietse van Buitenen - Added heatpump device
*/
public class MelCloudBindingConstants {
private static final String BINDING_ID = "melcloud";
// List of Bridge Type UIDs
public static final ThingTypeUID THING_TYPE_MELCLOUD_ACCOUNT = new ThingTypeUID(BINDING_ID, "melcloudaccount");
public static final ThingTypeUID THING_TYPE_HEATPUMPDEVICE = new ThingTypeUID(BINDING_ID, "heatpumpdevice");
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_ACDEVICE = new ThingTypeUID(BINDING_ID, "acdevice");
// List of all Channel ids
public static final String CHANNEL_POWER = "power";
public static final String CHANNEL_OPERATION_MODE = "operationMode";
public static final String CHANNEL_SET_TEMPERATURE = "setTemperature";
public static final String CHANNEL_FAN_SPEED = "fanSpeed";
public static final String CHANNEL_VANE_HORIZONTAL = "vaneHorizontal";
public static final String CHANNEL_VANE_VERTICAL = "vaneVertical";
public static final String CHANNEL_SET_TEMPERATURE_ZONE1 = "setTemperatureZone1";
public static final String CHANNEL_ROOM_TEMPERATURE_ZONE1 = "roomTemperatureZone1";
public static final String CHANNEL_FORCED_HOTWATERMODE = "forcedHotWaterMode";
public static final String CHANNEL_TANKWATERTEMPERATURE = "tankWaterTemperature";
// Read Only Channels
public static final String CHANNEL_ROOM_TEMPERATURE = "roomTemperature";
public static final String CHANNEL_LAST_COMMUNICATION = "lastCommunication";
public static final String CHANNEL_NEXT_COMMUNICATION = "nextCommunication";
public static final String CHANNEL_HAS_PENDING_COMMAND = "hasPendingCommand";
public static final String CHANNEL_OFFLINE = "offline";
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPE_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_MELCLOUD_ACCOUNT, THING_TYPE_ACDEVICE, THING_TYPE_HEATPUMPDEVICE)
.collect(Collectors.toSet()));
public static final Set<ThingTypeUID> DISCOVERABLE_THING_TYPE_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_ACDEVICE, THING_TYPE_HEATPUMPDEVICE).collect(Collectors.toSet()));
}

View File

@@ -0,0 +1,61 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal;
import static org.openhab.binding.melcloud.internal.MelCloudBindingConstants.*;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.melcloud.internal.handler.MelCloudAccountHandler;
import org.openhab.binding.melcloud.internal.handler.MelCloudDeviceHandler;
import org.openhab.binding.melcloud.internal.handler.MelCloudHeatpumpDeviceHandler;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Component;
/**
* The {@link MelCloudHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Luca Calcaterra - Initial contribution
* @author Wietse van Buitenen - Added heatpump device
*/
@Component(configurationPid = "binding.melcloud", service = ThingHandlerFactory.class)
public class MelCloudHandlerFactory extends BaseThingHandlerFactory {
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPE_UIDS.contains(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (THING_TYPE_MELCLOUD_ACCOUNT.equals(thingTypeUID)) {
MelCloudAccountHandler handler = new MelCloudAccountHandler((Bridge) thing);
return handler;
} else if (THING_TYPE_ACDEVICE.equals(thingTypeUID)) {
MelCloudDeviceHandler handler = new MelCloudDeviceHandler(thing);
return handler;
} else if (THING_TYPE_HEATPUMPDEVICE.equals(thingTypeUID)) {
MelCloudHeatpumpDeviceHandler handler = new MelCloudHeatpumpDeviceHandler(thing);
return handler;
}
return null;
}
}

View File

@@ -0,0 +1,214 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
import org.openhab.core.io.net.http.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
/**
* The {@link MelCloudConnection} Manage connection to Mitsubishi Cloud (MelCloud).
*
* @author Luca Calcaterra - Initial Contribution
* @author Pauli Anttila - Refactoring
* @author Wietse van Buitenen - Return all devices, added heatpump device
*/
public class MelCloudConnection {
private static final String LOGIN_URL = "https://app.melcloud.com/Mitsubishi.Wifi.Client/Login/ClientLogin";
private static final String DEVICE_LIST_URL = "https://app.melcloud.com/Mitsubishi.Wifi.Client/User/ListDevices";
private static final String DEVICE_URL = "https://app.melcloud.com/Mitsubishi.Wifi.Client/Device";
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()
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
private final Logger logger = LoggerFactory.getLogger(MelCloudConnection.class);
private boolean isConnected = false;
private String sessionKey;
public void login(String username, String password, int languageId)
throws MelCloudCommException, MelCloudLoginException {
setConnected(false);
sessionKey = null;
JsonObject jsonReq = new JsonObject();
jsonReq.addProperty("Email", username);
jsonReq.addProperty("Password", password);
jsonReq.addProperty("Language", languageId);
jsonReq.addProperty("AppVersion", "1.17.5.0");
jsonReq.addProperty("Persist", false);
jsonReq.addProperty("CaptchaResponse", (String) null);
InputStream data = new ByteArrayInputStream(jsonReq.toString().getBytes(StandardCharsets.UTF_8));
try {
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);
if (resp.getErrorId() != null) {
String errorMsg = String.format("Login failed, error code: %s", resp.getErrorId());
if (resp.getErrorMessage() != null) {
errorMsg = String.format("%s (%s)", errorMsg, resp.getErrorMessage());
}
throw new MelCloudLoginException(errorMsg);
}
sessionKey = resp.getLoginData().getContextKey();
setConnected(true);
} catch (IOException | JsonSyntaxException e) {
throw new MelCloudCommException(String.format("Login error, reason: %s", e.getMessage()), e);
}
}
public List<Device> fetchDeviceList() throws MelCloudCommException {
assertConnected();
try {
String response = HttpUtil.executeUrl("GET", DEVICE_LIST_URL, getHeaderProperties(), null, null,
TIMEOUT_MILLISECONDS);
logger.debug("Device list response: {}", response);
List<Device> devices = new ArrayList<>();
ListDevicesResponse[] buildings = gson.fromJson(response, ListDevicesResponse[].class);
Arrays.asList(buildings).forEach(building -> {
if (building.getStructure().getDevices() != null) {
devices.addAll(building.getStructure().getDevices());
}
building.getStructure().getAreas().forEach(area -> {
if (area.getDevices() != null) {
devices.addAll(area.getDevices());
}
});
building.getStructure().getFloors().forEach(floor -> {
if (floor.getDevices() != null) {
devices.addAll(floor.getDevices());
}
floor.getAreas().forEach(area -> {
if (area.getDevices() != null) {
devices.addAll(area.getDevices());
}
});
});
});
logger.debug("Found {} devices", devices.size());
return devices;
} catch (IOException | JsonSyntaxException e) {
setConnected(false);
throw new MelCloudCommException("Error occurred during device list poll", e);
}
}
public DeviceStatus fetchDeviceStatus(int deviceId, int buildingId) throws MelCloudCommException {
assertConnected();
String url = DEVICE_URL + String.format("/Get?id=%d&buildingID=%d", deviceId, buildingId);
try {
String response = HttpUtil.executeUrl("GET", url, getHeaderProperties(), null, null, TIMEOUT_MILLISECONDS);
logger.debug("Device status response: {}", response);
DeviceStatus deviceStatus = gson.fromJson(response, DeviceStatus.class);
return deviceStatus;
} catch (IOException | JsonSyntaxException e) {
setConnected(false);
throw new MelCloudCommException("Error occurred during device status fetch", e);
}
}
public DeviceStatus sendDeviceStatus(DeviceStatus deviceStatus) throws MelCloudCommException {
assertConnected();
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);
} catch (IOException | JsonSyntaxException e) {
setConnected(false);
throw new MelCloudCommException("Error occurred during device command sending", e);
}
}
public HeatpumpDeviceStatus fetchHeatpumpDeviceStatus(int deviceId, int buildingId) throws MelCloudCommException {
assertConnected();
String url = DEVICE_URL + String.format("/Get?id=%d&buildingID=%d", deviceId, buildingId);
try {
String response = HttpUtil.executeUrl("GET", url, getHeaderProperties(), null, null, TIMEOUT_MILLISECONDS);
logger.debug("Device heatpump status response: {}", response);
HeatpumpDeviceStatus heatpumpDeviceStatus = gson.fromJson(response, HeatpumpDeviceStatus.class);
return heatpumpDeviceStatus;
} catch (IOException | JsonSyntaxException e) {
setConnected(false);
throw new MelCloudCommException("Error occurred during heatpump device status fetch", e);
}
}
public HeatpumpDeviceStatus sendHeatpumpDeviceStatus(HeatpumpDeviceStatus heatpumpDeviceStatus)
throws MelCloudCommException {
assertConnected();
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);
} catch (IOException | JsonSyntaxException e) {
setConnected(false);
throw new MelCloudCommException("Error occurred during heatpump device command sending", e);
}
}
public synchronized boolean isConnected() {
return isConnected;
}
private synchronized void setConnected(boolean state) {
isConnected = state;
}
private Properties getHeaderProperties() {
Properties headers = new Properties();
headers.put("X-MitsContextKey", sessionKey);
return headers;
}
private void assertConnected() throws MelCloudCommException {
if (!isConnected) {
throw new MelCloudCommException("Not connected to MELCloud");
}
}
}

View File

@@ -0,0 +1,148 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import java.util.List;
import com.google.gson.annotations.Expose;
/**
* {@link Area} provides area specific information for JSON data returned from MELCloud API
* Area Data
* Generated with jsonschema2pojo
*
* @author Wietse van Buitenen - Initial contribution
*/
public class Area {
@Expose
private Integer iD;
@Expose
private String name;
@Expose
private Integer buildingId;
@Expose
private Integer floorId;
@Expose
private Integer accessLevel;
@Expose
private Boolean directAccess;
@Expose
private Object endDate;
@Expose
private Integer minTemperature;
@Expose
private Integer maxTemperature;
@Expose
private Boolean expanded;
@Expose
private List<Device> devices = null;
public Integer getID() {
return iD;
}
public void setID(Integer iD) {
this.iD = iD;
}
public Integer getBuildingId() {
return buildingId;
}
public void setBuildingId(Integer buildingId) {
this.buildingId = buildingId;
}
public Integer getFloorId() {
return floorId;
}
public void setFloorId(Integer floorId) {
this.floorId = floorId;
}
public Integer getAccessLevel() {
return accessLevel;
}
public void setAccessLevel(Integer accessLevel) {
this.accessLevel = accessLevel;
}
public Boolean getDirectAccess() {
return directAccess;
}
public void setDirectAccess(Boolean directAccess) {
this.directAccess = directAccess;
}
public Object getEndDate() {
return endDate;
}
public void setEndDate(Object endDate) {
this.endDate = endDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Device> getDevices() {
return devices;
}
public void setDevices(List<Device> devices) {
this.devices = devices;
}
public Integer getMinTemperature() {
return minTemperature;
}
public void setMinTemperature(Integer minTemperature) {
this.minTemperature = minTemperature;
}
public Integer getMaxTemperature() {
return maxTemperature;
}
public void setMaxTemperature(Integer maxTemperature) {
this.maxTemperature = maxTemperature;
}
public Boolean getExpanded() {
return expanded;
}
public void setExpanded(Boolean expanded) {
this.expanded = expanded;
}
}

View File

@@ -0,0 +1,556 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import java.security.Permissions;
import java.util.List;
import com.google.gson.annotations.Expose;
/**
* The {@link Device} is responsible of JSON data For MELCloud API
* Device Structure.
* Generated with jsonschema2pojo
*
* @author Luca Calcaterra - Initial contribution
*/
public class Device {
@Expose
private Integer deviceID;
@Expose
private String deviceName;
@Expose
private Integer buildingID;
@Expose
private Object buildingName;
@Expose
private Object floorID;
@Expose
private Object floorName;
@Expose
private Object areaID;
@Expose
private Object areaName;
@Expose
private Integer imageID;
@Expose
private String installationDate;
@Expose
private Object lastServiceDate;
@Expose
private List<Preset> presets = null;
@Expose
private Object ownerID;
@Expose
private Object ownerName;
@Expose
private Object ownerEmail;
@Expose
private Integer accessLevel;
@Expose
private Boolean directAccess;
@Expose
private String endDate;
@Expose
private Object zone1Name;
@Expose
private Object zone2Name;
@Expose
private Integer minTemperature;
@Expose
private Integer maxTemperature;
@Expose
private Boolean hideVaneControls;
@Expose
private Boolean hideDryModeControl;
@Expose
private Boolean hideRoomTemperature;
@Expose
private Boolean hideSupplyTemperature;
@Expose
private Boolean hideOutdoorTemperature;
@Expose
private Object buildingCountry;
@Expose
private Object ownerCountry;
@Expose
private Integer adaptorType;
@Expose
private Integer type;
@Expose
private String macAddress;
@Expose
private String serialNumber;
@Expose
private DeviceProps device;
@Expose
private Integer diagnosticMode;
@Expose
private Object diagnosticEndDate;
@Expose
private Integer location;
@Expose
private Object detectedCountry;
@Expose
private Integer registrations;
@Expose
private Object localIPAddress;
@Expose
private Integer timeZone;
@Expose
private Object registReason;
@Expose
private Integer expectedCommand;
private Integer registRetry;
@Expose
private String dateCreated;
@Expose
private Object firmwareDeployment;
@Expose
private Boolean firmwareUpdateAborted;
@Expose
private Permissions permissions;
public Integer getDeviceID() {
return deviceID;
}
public void setDeviceID(Integer deviceID) {
this.deviceID = deviceID;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public Integer getBuildingID() {
return buildingID;
}
public void setBuildingID(Integer buildingID) {
this.buildingID = buildingID;
}
public Object getBuildingName() {
return buildingName;
}
public void setBuildingName(Object buildingName) {
this.buildingName = buildingName;
}
public Object getFloorID() {
return floorID;
}
public void setFloorID(Object floorID) {
this.floorID = floorID;
}
public Object getFloorName() {
return floorName;
}
public void setFloorName(Object floorName) {
this.floorName = floorName;
}
public Object getAreaID() {
return areaID;
}
public void setAreaID(Object areaID) {
this.areaID = areaID;
}
public Object getAreaName() {
return areaName;
}
public void setAreaName(Object areaName) {
this.areaName = areaName;
}
public Integer getImageID() {
return imageID;
}
public void setImageID(Integer imageID) {
this.imageID = imageID;
}
public String getInstallationDate() {
return installationDate;
}
public void setInstallationDate(String installationDate) {
this.installationDate = installationDate;
}
public Object getLastServiceDate() {
return lastServiceDate;
}
public void setLastServiceDate(Object lastServiceDate) {
this.lastServiceDate = lastServiceDate;
}
public List<Preset> getPresets() {
return presets;
}
public void setPresets(List<Preset> presets) {
this.presets = presets;
}
public Object getOwnerID() {
return ownerID;
}
public void setOwnerID(Object ownerID) {
this.ownerID = ownerID;
}
public Object getOwnerName() {
return ownerName;
}
public void setOwnerName(Object ownerName) {
this.ownerName = ownerName;
}
public Object getOwnerEmail() {
return ownerEmail;
}
public void setOwnerEmail(Object ownerEmail) {
this.ownerEmail = ownerEmail;
}
public Integer getAccessLevel() {
return accessLevel;
}
public void setAccessLevel(Integer accessLevel) {
this.accessLevel = accessLevel;
}
public Boolean getDirectAccess() {
return directAccess;
}
public void setDirectAccess(Boolean directAccess) {
this.directAccess = directAccess;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public Object getZone1Name() {
return zone1Name;
}
public void setZone1Name(Object zone1Name) {
this.zone1Name = zone1Name;
}
public Object getZone2Name() {
return zone2Name;
}
public void setZone2Name(Object zone2Name) {
this.zone2Name = zone2Name;
}
public Integer getMinTemperature() {
return minTemperature;
}
public void setMinTemperature(Integer minTemperature) {
this.minTemperature = minTemperature;
}
public Integer getMaxTemperature() {
return maxTemperature;
}
public void setMaxTemperature(Integer maxTemperature) {
this.maxTemperature = maxTemperature;
}
public Boolean getHideVaneControls() {
return hideVaneControls;
}
public void setHideVaneControls(Boolean hideVaneControls) {
this.hideVaneControls = hideVaneControls;
}
public Boolean getHideDryModeControl() {
return hideDryModeControl;
}
public void setHideDryModeControl(Boolean hideDryModeControl) {
this.hideDryModeControl = hideDryModeControl;
}
public Boolean getHideRoomTemperature() {
return hideRoomTemperature;
}
public void setHideRoomTemperature(Boolean hideRoomTemperature) {
this.hideRoomTemperature = hideRoomTemperature;
}
public Boolean getHideSupplyTemperature() {
return hideSupplyTemperature;
}
public void setHideSupplyTemperature(Boolean hideSupplyTemperature) {
this.hideSupplyTemperature = hideSupplyTemperature;
}
public Boolean getHideOutdoorTemperature() {
return hideOutdoorTemperature;
}
public void setHideOutdoorTemperature(Boolean hideOutdoorTemperature) {
this.hideOutdoorTemperature = hideOutdoorTemperature;
}
public Object getBuildingCountry() {
return buildingCountry;
}
public void setBuildingCountry(Object buildingCountry) {
this.buildingCountry = buildingCountry;
}
public Object getOwnerCountry() {
return ownerCountry;
}
public void setOwnerCountry(Object ownerCountry) {
this.ownerCountry = ownerCountry;
}
public Integer getAdaptorType() {
return adaptorType;
}
public void setAdaptorType(Integer adaptorType) {
this.adaptorType = adaptorType;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getMacAddress() {
return macAddress;
}
public void setMacAddress(String macAddress) {
this.macAddress = macAddress;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public DeviceProps getDeviceProps() {
return device;
}
public void setDeviceProps(DeviceProps device) {
this.device = device;
}
public Integer getDiagnosticMode() {
return diagnosticMode;
}
public void setDiagnosticMode(Integer diagnosticMode) {
this.diagnosticMode = diagnosticMode;
}
public Object getDiagnosticEndDate() {
return diagnosticEndDate;
}
public void setDiagnosticEndDate(Object diagnosticEndDate) {
this.diagnosticEndDate = diagnosticEndDate;
}
public Integer getLocation() {
return location;
}
public void setLocation(Integer location) {
this.location = location;
}
public Object getDetectedCountry() {
return detectedCountry;
}
public void setDetectedCountry(Object detectedCountry) {
this.detectedCountry = detectedCountry;
}
public Integer getRegistrations() {
return registrations;
}
public void setRegistrations(Integer registrations) {
this.registrations = registrations;
}
public Object getLocalIPAddress() {
return localIPAddress;
}
public void setLocalIPAddress(Object localIPAddress) {
this.localIPAddress = localIPAddress;
}
public Integer getTimeZone() {
return timeZone;
}
public void setTimeZone(Integer timeZone) {
this.timeZone = timeZone;
}
public Object getRegistReason() {
return registReason;
}
public void setRegistReason(Object registReason) {
this.registReason = registReason;
}
public Integer getExpectedCommand() {
return expectedCommand;
}
public void setExpectedCommand(Integer expectedCommand) {
this.expectedCommand = expectedCommand;
}
public Integer getRegistRetry() {
return registRetry;
}
public void setRegistRetry(Integer registRetry) {
this.registRetry = registRetry;
}
public String getDateCreated() {
return dateCreated;
}
public void setDateCreated(String dateCreated) {
this.dateCreated = dateCreated;
}
public Object getFirmwareDeployment() {
return firmwareDeployment;
}
public void setFirmwareDeployment(Object firmwareDeployment) {
this.firmwareDeployment = firmwareDeployment;
}
public Boolean getFirmwareUpdateAborted() {
return firmwareUpdateAborted;
}
public void setFirmwareUpdateAborted(Boolean firmwareUpdateAborted) {
this.firmwareUpdateAborted = firmwareUpdateAborted;
}
public Permissions getPermissions() {
return permissions;
}
public void setPermissions(Permissions permissions) {
this.permissions = permissions;
}
}

View File

@@ -0,0 +1,347 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import java.util.List;
import com.google.gson.annotations.Expose;
/**
* The {@link DeviceProps} is responsible of JSON data For MELCloud API
* Device Status data
* Generated with jsonschema2pojo
*
* @author Luca Calcaterra - Initial contribution
* @author Pauli Anttila - Fine tuned expose annotations
*/
public class DeviceStatus {
@Expose
private Integer effectiveFlags;
@Expose(serialize = false, deserialize = true)
private Object localIPAddress;
@Expose(serialize = false, deserialize = true)
private Double roomTemperature;
@Expose
private Double setTemperature;
@Expose
private Integer setFanSpeed;
@Expose
private Integer operationMode;
@Expose
private Integer vaneHorizontal;
@Expose
private Integer vaneVertical;
@Expose
private Object name;
@Expose(serialize = false, deserialize = true)
private Integer numberOfFanSpeeds;
@Expose(serialize = false, deserialize = true)
private List<WeatherObservation> weatherObservations = null;
@Expose(serialize = false, deserialize = true)
private Object errorMessage;
@Expose(serialize = false, deserialize = true)
private Integer errorCode;
@Expose(serialize = false, deserialize = true)
private Double defaultHeatingSetTemperature;
@Expose(serialize = false, deserialize = true)
private Double defaultCoolingSetTemperature;
@Expose(serialize = false, deserialize = true)
private Boolean hideVaneControls;
@Expose(serialize = false, deserialize = true)
private Boolean hideDryModeControl;
@Expose(serialize = false, deserialize = true)
private Integer roomTemperatureLabel;
@Expose(serialize = false, deserialize = true)
private Boolean inStandbyMode;
@Expose(serialize = false, deserialize = true)
private Integer temperatureIncrementOverride;
@Expose
private Integer deviceID;
@Expose(serialize = false, deserialize = true)
private Integer deviceType;
@Expose(serialize = false, deserialize = true)
private String lastCommunication;
@Expose(serialize = false, deserialize = true)
private String nextCommunication;
@Expose
private Boolean power;
@Expose
private Boolean hasPendingCommand;
@Expose(serialize = false, deserialize = true)
private Boolean offline;
@Expose(serialize = false, deserialize = true)
private Object scene;
@Expose(serialize = false, deserialize = true)
private Object sceneOwner;
public Integer getEffectiveFlags() {
return effectiveFlags;
}
public void setEffectiveFlags(Integer effectiveFlags) {
this.effectiveFlags = effectiveFlags;
}
public Object getLocalIPAddress() {
return localIPAddress;
}
public void setLocalIPAddress(Object localIPAddress) {
this.localIPAddress = localIPAddress;
}
public Double getRoomTemperature() {
return roomTemperature;
}
public void setRoomTemperature(Double roomTemperature) {
this.roomTemperature = roomTemperature;
}
public Double getSetTemperature() {
return setTemperature;
}
public void setSetTemperature(Double setTemperature) {
this.setTemperature = setTemperature;
}
public Integer getSetFanSpeed() {
return setFanSpeed;
}
public void setSetFanSpeed(Integer setFanSpeed) {
this.setFanSpeed = setFanSpeed;
}
public Integer getOperationMode() {
return operationMode;
}
public void setOperationMode(Integer operationMode) {
this.operationMode = operationMode;
}
public Integer getVaneHorizontal() {
return vaneHorizontal;
}
public void setVaneHorizontal(Integer vaneHorizontal) {
this.vaneHorizontal = vaneHorizontal;
}
public Integer getVaneVertical() {
return vaneVertical;
}
public void setVaneVertical(Integer vaneVertical) {
this.vaneVertical = vaneVertical;
}
public Object getName() {
return name;
}
public void setName(Object name) {
this.name = name;
}
public Integer getNumberOfFanSpeeds() {
return numberOfFanSpeeds;
}
public void setNumberOfFanSpeeds(Integer numberOfFanSpeeds) {
this.numberOfFanSpeeds = numberOfFanSpeeds;
}
public List<WeatherObservation> getWeatherObservations() {
return weatherObservations;
}
public void setWeatherObservations(List<WeatherObservation> weatherObservations) {
this.weatherObservations = weatherObservations;
}
public Object getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(Object errorMessage) {
this.errorMessage = errorMessage;
}
public Integer getErrorCode() {
return errorCode;
}
public void setErrorCode(Integer errorCode) {
this.errorCode = errorCode;
}
public Double getDefaultHeatingSetTemperature() {
return defaultHeatingSetTemperature;
}
public void setDefaultHeatingSetTemperature(Double defaultHeatingSetTemperature) {
this.defaultHeatingSetTemperature = defaultHeatingSetTemperature;
}
public Double getDefaultCoolingSetTemperature() {
return defaultCoolingSetTemperature;
}
public void setDefaultCoolingSetTemperature(Double defaultCoolingSetTemperature) {
this.defaultCoolingSetTemperature = defaultCoolingSetTemperature;
}
public Boolean getHideVaneControls() {
return hideVaneControls;
}
public void setHideVaneControls(Boolean hideVaneControls) {
this.hideVaneControls = hideVaneControls;
}
public Boolean getHideDryModeControl() {
return hideDryModeControl;
}
public void setHideDryModeControl(Boolean hideDryModeControl) {
this.hideDryModeControl = hideDryModeControl;
}
public Integer getRoomTemperatureLabel() {
return roomTemperatureLabel;
}
public void setRoomTemperatureLabel(Integer roomTemperatureLabel) {
this.roomTemperatureLabel = roomTemperatureLabel;
}
public Boolean getInStandbyMode() {
return inStandbyMode;
}
public void setInStandbyMode(Boolean inStandbyMode) {
this.inStandbyMode = inStandbyMode;
}
public Integer getTemperatureIncrementOverride() {
return temperatureIncrementOverride;
}
public void setTemperatureIncrementOverride(Integer temperatureIncrementOverride) {
this.temperatureIncrementOverride = temperatureIncrementOverride;
}
public Integer getDeviceID() {
return deviceID;
}
public void setDeviceID(Integer deviceID) {
this.deviceID = deviceID;
}
public Integer getDeviceType() {
return deviceType;
}
public void setDeviceType(Integer deviceType) {
this.deviceType = deviceType;
}
public String getLastCommunication() {
return lastCommunication;
}
public void setLastCommunication(String lastCommunication) {
this.lastCommunication = lastCommunication;
}
public String getNextCommunication() {
return nextCommunication;
}
public void setNextCommunication(String nextCommunication) {
this.nextCommunication = nextCommunication;
}
public Boolean getPower() {
return power;
}
public void setPower(Boolean power) {
this.power = power;
}
public Boolean getHasPendingCommand() {
return hasPendingCommand;
}
public void setHasPendingCommand(Boolean hasPendingCommand) {
this.hasPendingCommand = hasPendingCommand;
}
public Boolean getOffline() {
return offline;
}
public void setOffline(Boolean offline) {
this.offline = offline;
}
public Object getScene() {
return scene;
}
public void setScene(Object scene) {
this.scene = scene;
}
public Object getSceneOwner() {
return sceneOwner;
}
public void setSceneOwner(Object sceneOwner) {
this.sceneOwner = sceneOwner;
}
}

View File

@@ -0,0 +1,148 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import java.util.List;
import com.google.gson.annotations.Expose;
/**
* {@link Floor} provides floor specific information for JSON data returned from MELCloud API
* Floor Data
* Generated with jsonschema2pojo
*
* @author Wietse van Buitenen - Initial contribution
*/
public class Floor {
@Expose
private Integer iD;
@Expose
private String name;
@Expose
private Integer buildingId;
@Expose
private Integer accessLevel;
@Expose
private Boolean directAccess;
@Expose
private Object endDate;
@Expose
private List<Area> areas = null;
@Expose
private List<Device> devices = null;
@Expose
private Integer minTemperature;
@Expose
private Integer maxTemperature;
@Expose
private Boolean expanded;
public Integer getID() {
return iD;
}
public void setID(Integer iD) {
this.iD = iD;
}
public Integer getBuildingId() {
return buildingId;
}
public void setBuildingId(Integer buildingId) {
this.buildingId = buildingId;
}
public Integer getAccessLevel() {
return accessLevel;
}
public void setAccessLevel(Integer accessLevel) {
this.accessLevel = accessLevel;
}
public Boolean getDirectAccess() {
return directAccess;
}
public void setDirectAccess(Boolean directAccess) {
this.directAccess = directAccess;
}
public Object getEndDate() {
return endDate;
}
public void setEndDate(Object endDate) {
this.endDate = endDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Area> getAreas() {
return areas;
}
public void setAreas(List<Area> areas) {
this.areas = areas;
}
public List<Device> getDevices() {
return devices;
}
public void setDevices(List<Device> devices) {
this.devices = devices;
}
public Integer getMinTemperature() {
return minTemperature;
}
public void setMinTemperature(Integer minTemperature) {
this.minTemperature = minTemperature;
}
public Integer getMaxTemperature() {
return maxTemperature;
}
public void setMaxTemperature(Integer maxTemperature) {
this.maxTemperature = maxTemperature;
}
public Boolean getExpanded() {
return expanded;
}
public void setExpanded(Boolean expanded) {
this.expanded = expanded;
}
}

View File

@@ -0,0 +1,477 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import java.util.List;
import com.google.gson.annotations.Expose;
/**
* {@link HeatpumpDeviceStatus} is the JSON data we receive from the MELCloud API
* when performing a request to DeviceType 1.
* Generated with jsonschema2pojo
*
* @author Wietse van Buitenen - Initial contribution
*/
public class HeatpumpDeviceStatus {
@Expose
private Long effectiveFlags;
@Expose(serialize = false, deserialize = true)
private Object localIPAddress;
@Expose
private Double setTemperatureZone1;
@Expose
private Double setTemperatureZone2;
@Expose(serialize = false, deserialize = true)
private Double roomTemperatureZone1;
@Expose(serialize = false, deserialize = true)
private Double roomTemperatureZone2;
@Expose
private Integer operationMode;
@Expose
private Integer operationModeZone1;
@Expose
private Integer operationModeZone2;
@Expose(serialize = false, deserialize = true)
private List<WeatherObservation> weatherObservations = null;
@Expose(serialize = false, deserialize = true)
private Object errorMessage;
@Expose(serialize = false, deserialize = true)
private Integer errorCode;
@Expose
private Double setHeatFlowTemperatureZone1;
@Expose
private Double setHeatFlowTemperatureZone2;
@Expose
private Double setCoolFlowTemperatureZone1;
@Expose
private Double setCoolFlowTemperatureZone2;
@Expose
private Integer hCControlType;
@Expose(serialize = false, deserialize = true)
private Double tankWaterTemperature;
@Expose
private Double setTankWaterTemperature;
@Expose
private Boolean forcedHotWaterMode;
@Expose
private Integer unitStatus;
@Expose
private Double outdoorTemperature;
@Expose
private Boolean ecoHotWater;
@Expose
private Object zone1Name;
@Expose
private Object zone2Name;
@Expose
private Boolean holidayMode;
@Expose
private Boolean prohibitZone1;
@Expose
private Boolean prohibitZone2;
@Expose
private Boolean prohibitHotWater;
@Expose
private Integer temperatureIncrementOverride;
@Expose
private Boolean idleZone1;
@Expose
private Boolean idleZone2;
@Expose
private Integer deviceID;
@Expose
private Integer deviceType;
@Expose(serialize = false, deserialize = true)
private String lastCommunication;
@Expose(serialize = false, deserialize = true)
private String nextCommunication;
@Expose
private Boolean power;
@Expose(serialize = false, deserialize = true)
private Boolean hasPendingCommand;
@Expose(serialize = false, deserialize = true)
private Boolean offline;
@Expose
private Object scene;
@Expose
private Object sceneOwner;
public Long getEffectiveFlags() {
return effectiveFlags;
}
public void setEffectiveFlags(Long effectiveFlags) {
this.effectiveFlags = effectiveFlags;
}
public Object getLocalIPAddress() {
return localIPAddress;
}
public void setLocalIPAddress(Object localIPAddress) {
this.localIPAddress = localIPAddress;
}
public Double getSetTemperatureZone1() {
return setTemperatureZone1;
}
public void setSetTemperatureZone1(Double setTemperatureZone1) {
this.setTemperatureZone1 = setTemperatureZone1;
}
public Double getSetTemperatureZone2() {
return setTemperatureZone2;
}
public void setSetTemperatureZone2(Double setTemperatureZone2) {
this.setTemperatureZone2 = setTemperatureZone2;
}
public Double getRoomTemperatureZone1() {
return roomTemperatureZone1;
}
public void setRoomTemperatureZone1(Double roomTemperatureZone1) {
this.roomTemperatureZone1 = roomTemperatureZone1;
}
public Double getRoomTemperatureZone2() {
return roomTemperatureZone2;
}
public void setRoomTemperatureZone2(Double roomTemperatureZone2) {
this.roomTemperatureZone2 = roomTemperatureZone2;
}
public Integer getOperationMode() {
return operationMode;
}
public void setOperationMode(Integer operationMode) {
this.operationMode = operationMode;
}
public Integer getOperationModeZone1() {
return operationModeZone1;
}
public void setOperationModeZone1(Integer operationModeZone1) {
this.operationModeZone1 = operationModeZone1;
}
public Integer getOperationModeZone2() {
return operationModeZone2;
}
public void setOperationModeZone2(Integer operationModeZone2) {
this.operationModeZone2 = operationModeZone2;
}
public List<WeatherObservation> getWeatherObservations() {
return weatherObservations;
}
public void setWeatherObservations(List<WeatherObservation> weatherObservations) {
this.weatherObservations = weatherObservations;
}
public Object getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(Object errorMessage) {
this.errorMessage = errorMessage;
}
public Integer getErrorCode() {
return errorCode;
}
public void setErrorCode(Integer errorCode) {
this.errorCode = errorCode;
}
public Double getSetHeatFlowTemperatureZone1() {
return setHeatFlowTemperatureZone1;
}
public void setSetHeatFlowTemperatureZone1(Double setHeatFlowTemperatureZone1) {
this.setHeatFlowTemperatureZone1 = setHeatFlowTemperatureZone1;
}
public Double getSetHeatFlowTemperatureZone2() {
return setHeatFlowTemperatureZone2;
}
public void setSetHeatFlowTemperatureZone2(Double setHeatFlowTemperatureZone2) {
this.setHeatFlowTemperatureZone2 = setHeatFlowTemperatureZone2;
}
public Double getSetCoolFlowTemperatureZone1() {
return setCoolFlowTemperatureZone1;
}
public void setSetCoolFlowTemperatureZone1(Double setCoolFlowTemperatureZone1) {
this.setCoolFlowTemperatureZone1 = setCoolFlowTemperatureZone1;
}
public Double getSetCoolFlowTemperatureZone2() {
return setCoolFlowTemperatureZone2;
}
public void setSetCoolFlowTemperatureZone2(Double setCoolFlowTemperatureZone2) {
this.setCoolFlowTemperatureZone2 = setCoolFlowTemperatureZone2;
}
public Integer getHCControlType() {
return hCControlType;
}
public void setHCControlType(Integer hCControlType) {
this.hCControlType = hCControlType;
}
public Double getTankWaterTemperature() {
return tankWaterTemperature;
}
public void setTankWaterTemperature(Double tankWaterTemperature) {
this.tankWaterTemperature = tankWaterTemperature;
}
public Double getSetTankWaterTemperature() {
return setTankWaterTemperature;
}
public void setSetTankWaterTemperature(Double setTankWaterTemperature) {
this.setTankWaterTemperature = setTankWaterTemperature;
}
public Boolean getForcedHotWaterMode() {
return forcedHotWaterMode;
}
public void setForcedHotWaterMode(Boolean forcedHotWaterMode) {
this.forcedHotWaterMode = forcedHotWaterMode;
}
public Integer getUnitStatus() {
return unitStatus;
}
public void setUnitStatus(Integer unitStatus) {
this.unitStatus = unitStatus;
}
public Double getOutdoorTemperature() {
return outdoorTemperature;
}
public void setOutdoorTemperature(Double outdoorTemperature) {
this.outdoorTemperature = outdoorTemperature;
}
public Boolean getEcoHotWater() {
return ecoHotWater;
}
public void setEcoHotWater(Boolean ecoHotWater) {
this.ecoHotWater = ecoHotWater;
}
public Object getZone1Name() {
return zone1Name;
}
public void setZone1Name(Object zone1Name) {
this.zone1Name = zone1Name;
}
public Object getZone2Name() {
return zone2Name;
}
public void setZone2Name(Object zone2Name) {
this.zone2Name = zone2Name;
}
public Boolean getHolidayMode() {
return holidayMode;
}
public void setHolidayMode(Boolean holidayMode) {
this.holidayMode = holidayMode;
}
public Boolean getProhibitZone1() {
return prohibitZone1;
}
public void setProhibitZone1(Boolean prohibitZone1) {
this.prohibitZone1 = prohibitZone1;
}
public Boolean getProhibitZone2() {
return prohibitZone2;
}
public void setProhibitZone2(Boolean prohibitZone2) {
this.prohibitZone2 = prohibitZone2;
}
public Boolean getProhibitHotWater() {
return prohibitHotWater;
}
public void setProhibitHotWater(Boolean prohibitHotWater) {
this.prohibitHotWater = prohibitHotWater;
}
public Integer getTemperatureIncrementOverride() {
return temperatureIncrementOverride;
}
public void setTemperatureIncrementOverride(Integer temperatureIncrementOverride) {
this.temperatureIncrementOverride = temperatureIncrementOverride;
}
public Boolean getIdleZone1() {
return idleZone1;
}
public void setIdleZone1(Boolean idleZone1) {
this.idleZone1 = idleZone1;
}
public Boolean getIdleZone2() {
return idleZone2;
}
public void setIdleZone2(Boolean idleZone2) {
this.idleZone2 = idleZone2;
}
public Integer getDeviceID() {
return deviceID;
}
public void setDeviceID(Integer deviceID) {
this.deviceID = deviceID;
}
public Integer getDeviceType() {
return deviceType;
}
public void setDeviceType(Integer deviceType) {
this.deviceType = deviceType;
}
public String getLastCommunication() {
return lastCommunication;
}
public void setLastCommunication(String lastCommunication) {
this.lastCommunication = lastCommunication;
}
public String getNextCommunication() {
return nextCommunication;
}
public void setNextCommunication(String nextCommunication) {
this.nextCommunication = nextCommunication;
}
public Boolean getPower() {
return power;
}
public void setPower(Boolean power) {
this.power = power;
}
public Boolean getHasPendingCommand() {
return hasPendingCommand;
}
public void setHasPendingCommand(Boolean hasPendingCommand) {
this.hasPendingCommand = hasPendingCommand;
}
public Boolean getOffline() {
return offline;
}
public void setOffline(Boolean offline) {
this.offline = offline;
}
public Object getScene() {
return scene;
}
public void setScene(Object scene) {
this.scene = scene;
}
public Object getSceneOwner() {
return sceneOwner;
}
public void setSceneOwner(Object sceneOwner) {
this.sceneOwner = sceneOwner;
}
}

View File

@@ -0,0 +1,445 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* The {@link ListDevicesResponse} is responsible of JSON data For MELCloud API
* Response of Devices List.
* Generated with jsonschema2pojo
*
* @author Luca Calcaterra - Initial contribution
*/
public class ListDevicesResponse {
@Expose
private Integer iD;
@Expose
private String name;
@Expose
private String addressLine1;
@Expose
private Object addressLine2;
@Expose
private String city;
@Expose
private String postcode;
@Expose
private Double latitude;
@Expose
private Double longitude;
@Expose
private Object district;
@Expose
private Boolean fPDefined;
@Expose
private Boolean fPEnabled;
@Expose
private Integer fPMinTemperature;
@Expose
private Integer fPMaxTemperature;
@Expose
private Boolean hMDefined;
@Expose
private Boolean hMEnabled;
@Expose
private Object hMStartDate;
@Expose
private Object hMEndDate;
@Expose
private Integer buildingType;
@Expose
private Integer propertyType;
@Expose
private String dateBuilt;
@Expose
private Boolean hasGasSupply;
@Expose
private String locationLookupDate;
@Expose
private Integer country;
@Expose
private Integer timeZoneContinent;
@Expose
private Integer timeZoneCity;
@Expose
private Integer timeZone;
@Expose
private Integer location;
@Expose
private Boolean coolingDisabled;
@Expose
private Boolean expanded;
@Expose
private Structure structure;
@Expose
private Integer accessLevel;
@Expose
private Boolean directAccess;
@Expose
private Integer minTemperature;
@Expose
private Integer maxTemperature;
@Expose
private Object owner;
@Expose
private String endDate;
@SerializedName("iDateBuilt")
@Expose
private Object iDateBuilt;
@Expose
private QuantizedCoordinates quantizedCoordinates;
public Integer getID() {
return iD;
}
public void setID(Integer iD) {
this.iD = iD;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public Object getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(Object addressLine2) {
this.addressLine2 = addressLine2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Object getDistrict() {
return district;
}
public void setDistrict(Object district) {
this.district = district;
}
public Boolean getFPDefined() {
return fPDefined;
}
public void setFPDefined(Boolean fPDefined) {
this.fPDefined = fPDefined;
}
public Boolean getFPEnabled() {
return fPEnabled;
}
public void setFPEnabled(Boolean fPEnabled) {
this.fPEnabled = fPEnabled;
}
public Integer getFPMinTemperature() {
return fPMinTemperature;
}
public void setFPMinTemperature(Integer fPMinTemperature) {
this.fPMinTemperature = fPMinTemperature;
}
public Integer getFPMaxTemperature() {
return fPMaxTemperature;
}
public void setFPMaxTemperature(Integer fPMaxTemperature) {
this.fPMaxTemperature = fPMaxTemperature;
}
public Boolean getHMDefined() {
return hMDefined;
}
public void setHMDefined(Boolean hMDefined) {
this.hMDefined = hMDefined;
}
public Boolean getHMEnabled() {
return hMEnabled;
}
public void setHMEnabled(Boolean hMEnabled) {
this.hMEnabled = hMEnabled;
}
public Object getHMStartDate() {
return hMStartDate;
}
public void setHMStartDate(Object hMStartDate) {
this.hMStartDate = hMStartDate;
}
public Object getHMEndDate() {
return hMEndDate;
}
public void setHMEndDate(Object hMEndDate) {
this.hMEndDate = hMEndDate;
}
public Integer getBuildingType() {
return buildingType;
}
public void setBuildingType(Integer buildingType) {
this.buildingType = buildingType;
}
public Integer getPropertyType() {
return propertyType;
}
public void setPropertyType(Integer propertyType) {
this.propertyType = propertyType;
}
public String getDateBuilt() {
return dateBuilt;
}
public void setDateBuilt(String dateBuilt) {
this.dateBuilt = dateBuilt;
}
public Boolean getHasGasSupply() {
return hasGasSupply;
}
public void setHasGasSupply(Boolean hasGasSupply) {
this.hasGasSupply = hasGasSupply;
}
public String getLocationLookupDate() {
return locationLookupDate;
}
public void setLocationLookupDate(String locationLookupDate) {
this.locationLookupDate = locationLookupDate;
}
public Integer getCountry() {
return country;
}
public void setCountry(Integer country) {
this.country = country;
}
public Integer getTimeZoneContinent() {
return timeZoneContinent;
}
public void setTimeZoneContinent(Integer timeZoneContinent) {
this.timeZoneContinent = timeZoneContinent;
}
public Integer getTimeZoneCity() {
return timeZoneCity;
}
public void setTimeZoneCity(Integer timeZoneCity) {
this.timeZoneCity = timeZoneCity;
}
public Integer getTimeZone() {
return timeZone;
}
public void setTimeZone(Integer timeZone) {
this.timeZone = timeZone;
}
public Integer getLocation() {
return location;
}
public void setLocation(Integer location) {
this.location = location;
}
public Boolean getCoolingDisabled() {
return coolingDisabled;
}
public void setCoolingDisabled(Boolean coolingDisabled) {
this.coolingDisabled = coolingDisabled;
}
public Boolean getExpanded() {
return expanded;
}
public void setExpanded(Boolean expanded) {
this.expanded = expanded;
}
public Structure getStructure() {
return structure;
}
public void setStructure(Structure structure) {
this.structure = structure;
}
public Integer getAccessLevel() {
return accessLevel;
}
public void setAccessLevel(Integer accessLevel) {
this.accessLevel = accessLevel;
}
public Boolean getDirectAccess() {
return directAccess;
}
public void setDirectAccess(Boolean directAccess) {
this.directAccess = directAccess;
}
public Integer getMinTemperature() {
return minTemperature;
}
public void setMinTemperature(Integer minTemperature) {
this.minTemperature = minTemperature;
}
public Integer getMaxTemperature() {
return maxTemperature;
}
public void setMaxTemperature(Integer maxTemperature) {
this.maxTemperature = maxTemperature;
}
public Object getOwner() {
return owner;
}
public void setOwner(Object owner) {
this.owner = owner;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public Object getIDateBuilt() {
return iDateBuilt;
}
public void setIDateBuilt(Object iDateBuilt) {
this.iDateBuilt = iDateBuilt;
}
public QuantizedCoordinates getQuantizedCoordinates() {
return quantizedCoordinates;
}
public void setQuantizedCoordinates(QuantizedCoordinates quantizedCoordinates) {
this.quantizedCoordinates = quantizedCoordinates;
}
}

View File

@@ -0,0 +1,159 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import java.util.List;
import com.google.gson.annotations.Expose;
/**
* The {@link LoginClientResponse} is responsible of JSON data For MELCloud API
* Response Data of Login.
* Generated with jsonschema2pojo
*
* @author Luca Calcaterra - Initial contribution
*/
public class LoginClientResponse {
@Expose
private Object errorId;
@Expose
private Object errorMessage;
@Expose
private Integer loginStatus;
@Expose
private Integer userId;
@Expose
private Object randomKey;
@Expose
private Object appVersionAnnouncement;
@Expose
private LoginData loginData;
@Expose
private List<Object> listPendingInvite = null;
@Expose
private List<Object> listOwnershipChangeRequest = null;
@Expose
private List<Object> listPendingAnnouncement = null;
@Expose
private Integer loginMinutes;
@Expose
private Integer loginAttempts;
public Object getErrorId() {
return errorId;
}
public void setErrorId(Object errorId) {
this.errorId = errorId;
}
public Object getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(Object errorMessage) {
this.errorMessage = errorMessage;
}
public Integer getLoginStatus() {
return loginStatus;
}
public void setLoginStatus(Integer loginStatus) {
this.loginStatus = loginStatus;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public Object getRandomKey() {
return randomKey;
}
public void setRandomKey(Object randomKey) {
this.randomKey = randomKey;
}
public Object getAppVersionAnnouncement() {
return appVersionAnnouncement;
}
public void setAppVersionAnnouncement(Object appVersionAnnouncement) {
this.appVersionAnnouncement = appVersionAnnouncement;
}
public LoginData getLoginData() {
return loginData;
}
public void setLoginData(LoginData loginData) {
this.loginData = loginData;
}
public List<Object> getListPendingInvite() {
return listPendingInvite;
}
public void setListPendingInvite(List<Object> listPendingInvite) {
this.listPendingInvite = listPendingInvite;
}
public List<Object> getListOwnershipChangeRequest() {
return listOwnershipChangeRequest;
}
public void setListOwnershipChangeRequest(List<Object> listOwnershipChangeRequest) {
this.listOwnershipChangeRequest = listOwnershipChangeRequest;
}
public List<Object> getListPendingAnnouncement() {
return listPendingAnnouncement;
}
public void setListPendingAnnouncement(List<Object> listPendingAnnouncement) {
this.listPendingAnnouncement = listPendingAnnouncement;
}
public Integer getLoginMinutes() {
return loginMinutes;
}
public void setLoginMinutes(Integer loginMinutes) {
this.loginMinutes = loginMinutes;
}
public Integer getLoginAttempts() {
return loginAttempts;
}
public void setLoginAttempts(Integer loginAttempts) {
this.loginAttempts = loginAttempts;
}
}

View File

@@ -0,0 +1,509 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import com.google.gson.annotations.Expose;
/**
* The {@link LoginData} is responsible of JSON data For MELCloud API
* LoginData for Login Request.
* Generated with jsonschema2pojo
*
* @author Luca Calcaterra - Initial contribution
*/
public class LoginData {
@Expose
private String contextKey;
@Expose
private Integer client;
@Expose
private Integer terms;
@Expose
private Integer aL;
@Expose
private Integer mL;
@Expose
private Boolean cMI;
@Expose
private Boolean isStaff;
@Expose
private Boolean cUTF;
@Expose
private Boolean cAA;
@Expose
private Boolean receiveCountryNotifications;
@Expose
private Boolean receiveAllNotifications;
@Expose
private Boolean cACA;
@Expose
private Boolean cAGA;
@Expose
private Integer maximumDevices;
@Expose
private Boolean showDiagnostics;
@Expose
private Integer language;
@Expose
private Integer country;
@Expose
private Integer realClient;
@Expose
private String name;
@Expose
private Boolean useFahrenheit;
@Expose
private Integer duration;
@Expose
private String expiry;
@Expose
private Boolean cMSC;
@Expose
private Object partnerApplicationVersion;
@Expose
private Boolean emailSettingsReminderShown;
@Expose
private Integer emailUnitErrors;
@Expose
private Integer emailCommsErrors;
@Expose
private Boolean isImpersonated;
@Expose
private String languageCode;
@Expose
private String countryName;
@Expose
private String currencySymbol;
@Expose
private String supportEmailAddress;
@Expose
private String dateSeperator;
@Expose
private String timeSeperator;
@Expose
private String atwLogoFile;
@Expose
private Boolean dECCReport;
@Expose
private Boolean cSVReport1min;
@Expose
private Boolean hidePresetPanel;
@Expose
private Boolean emailSettingsReminderRequired;
@Expose
private Object termsText;
@Expose
private Boolean mapView;
@Expose
private Integer mapZoom;
@Expose
private Double mapLongitude;
@Expose
private Double mapLatitude;
public String getContextKey() {
return contextKey;
}
public void setContextKey(String contextKey) {
this.contextKey = contextKey;
}
public Integer getClient() {
return client;
}
public void setClient(Integer client) {
this.client = client;
}
public Integer getTerms() {
return terms;
}
public void setTerms(Integer terms) {
this.terms = terms;
}
public Integer getAL() {
return aL;
}
public void setAL(Integer aL) {
this.aL = aL;
}
public Integer getML() {
return mL;
}
public void setML(Integer mL) {
this.mL = mL;
}
public Boolean getCMI() {
return cMI;
}
public void setCMI(Boolean cMI) {
this.cMI = cMI;
}
public Boolean getIsStaff() {
return isStaff;
}
public void setIsStaff(Boolean isStaff) {
this.isStaff = isStaff;
}
public Boolean getCUTF() {
return cUTF;
}
public void setCUTF(Boolean cUTF) {
this.cUTF = cUTF;
}
public Boolean getCAA() {
return cAA;
}
public void setCAA(Boolean cAA) {
this.cAA = cAA;
}
public Boolean getReceiveCountryNotifications() {
return receiveCountryNotifications;
}
public void setReceiveCountryNotifications(Boolean receiveCountryNotifications) {
this.receiveCountryNotifications = receiveCountryNotifications;
}
public Boolean getReceiveAllNotifications() {
return receiveAllNotifications;
}
public void setReceiveAllNotifications(Boolean receiveAllNotifications) {
this.receiveAllNotifications = receiveAllNotifications;
}
public Boolean getCACA() {
return cACA;
}
public void setCACA(Boolean cACA) {
this.cACA = cACA;
}
public Boolean getCAGA() {
return cAGA;
}
public void setCAGA(Boolean cAGA) {
this.cAGA = cAGA;
}
public Integer getMaximumDevices() {
return maximumDevices;
}
public void setMaximumDevices(Integer maximumDevices) {
this.maximumDevices = maximumDevices;
}
public Boolean getShowDiagnostics() {
return showDiagnostics;
}
public void setShowDiagnostics(Boolean showDiagnostics) {
this.showDiagnostics = showDiagnostics;
}
public Integer getLanguage() {
return language;
}
public void setLanguage(Integer language) {
this.language = language;
}
public Integer getCountry() {
return country;
}
public void setCountry(Integer country) {
this.country = country;
}
public Integer getRealClient() {
return realClient;
}
public void setRealClient(Integer realClient) {
this.realClient = realClient;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getUseFahrenheit() {
return useFahrenheit;
}
public void setUseFahrenheit(Boolean useFahrenheit) {
this.useFahrenheit = useFahrenheit;
}
public Integer getDuration() {
return duration;
}
public void setDuration(Integer duration) {
this.duration = duration;
}
public String getExpiry() {
return expiry;
}
public void setExpiry(String expiry) {
this.expiry = expiry;
}
public Boolean getCMSC() {
return cMSC;
}
public void setCMSC(Boolean cMSC) {
this.cMSC = cMSC;
}
public Object getPartnerApplicationVersion() {
return partnerApplicationVersion;
}
public void setPartnerApplicationVersion(Object partnerApplicationVersion) {
this.partnerApplicationVersion = partnerApplicationVersion;
}
public Boolean getEmailSettingsReminderShown() {
return emailSettingsReminderShown;
}
public void setEmailSettingsReminderShown(Boolean emailSettingsReminderShown) {
this.emailSettingsReminderShown = emailSettingsReminderShown;
}
public Integer getEmailUnitErrors() {
return emailUnitErrors;
}
public void setEmailUnitErrors(Integer emailUnitErrors) {
this.emailUnitErrors = emailUnitErrors;
}
public Integer getEmailCommsErrors() {
return emailCommsErrors;
}
public void setEmailCommsErrors(Integer emailCommsErrors) {
this.emailCommsErrors = emailCommsErrors;
}
public Boolean getIsImpersonated() {
return isImpersonated;
}
public void setIsImpersonated(Boolean isImpersonated) {
this.isImpersonated = isImpersonated;
}
public String getLanguageCode() {
return languageCode;
}
public void setLanguageCode(String languageCode) {
this.languageCode = languageCode;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public String getCurrencySymbol() {
return currencySymbol;
}
public void setCurrencySymbol(String currencySymbol) {
this.currencySymbol = currencySymbol;
}
public String getSupportEmailAddress() {
return supportEmailAddress;
}
public void setSupportEmailAddress(String supportEmailAddress) {
this.supportEmailAddress = supportEmailAddress;
}
public String getDateSeperator() {
return dateSeperator;
}
public void setDateSeperator(String dateSeperator) {
this.dateSeperator = dateSeperator;
}
public String getTimeSeperator() {
return timeSeperator;
}
public void setTimeSeperator(String timeSeperator) {
this.timeSeperator = timeSeperator;
}
public String getAtwLogoFile() {
return atwLogoFile;
}
public void setAtwLogoFile(String atwLogoFile) {
this.atwLogoFile = atwLogoFile;
}
public Boolean getDECCReport() {
return dECCReport;
}
public void setDECCReport(Boolean dECCReport) {
this.dECCReport = dECCReport;
}
public Boolean getCSVReport1min() {
return cSVReport1min;
}
public void setCSVReport1min(Boolean cSVReport1min) {
this.cSVReport1min = cSVReport1min;
}
public Boolean getHidePresetPanel() {
return hidePresetPanel;
}
public void setHidePresetPanel(Boolean hidePresetPanel) {
this.hidePresetPanel = hidePresetPanel;
}
public Boolean getEmailSettingsReminderRequired() {
return emailSettingsReminderRequired;
}
public void setEmailSettingsReminderRequired(Boolean emailSettingsReminderRequired) {
this.emailSettingsReminderRequired = emailSettingsReminderRequired;
}
public Object getTermsText() {
return termsText;
}
public void setTermsText(Object termsText) {
this.termsText = termsText;
}
public Boolean getMapView() {
return mapView;
}
public void setMapView(Boolean mapView) {
this.mapView = mapView;
}
public Integer getMapZoom() {
return mapZoom;
}
public void setMapZoom(Integer mapZoom) {
this.mapZoom = mapZoom;
}
public Double getMapLongitude() {
return mapLongitude;
}
public void setMapLongitude(Double mapLongitude) {
this.mapLongitude = mapLongitude;
}
public Double getMapLatitude() {
return mapLatitude;
}
public void setMapLatitude(Double mapLatitude) {
this.mapLatitude = mapLatitude;
}
}

View File

@@ -0,0 +1,157 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import com.google.gson.annotations.Expose;
/**
* The {@link Preset} is responsible of JSON data For MELCloud API
* Preset data
* Generated with jsonschema2pojo
*
* @author Luca Calcaterra - Initial contribution
*/
public class Preset {
@Expose
private Double setTemperature;
@Expose
private Boolean power;
@Expose
private Integer operationMode;
@Expose
private Integer vaneHorizontal;
@Expose
private Integer vaneVertical;
@Expose
private Integer fanSpeed;
@Expose
private Integer iD;
@Expose
private Integer client;
@Expose
private Integer deviceLocation;
@Expose
private Integer number;
@Expose
private String configuration;
@Expose
private String numberDescription;
public Double getSetTemperature() {
return setTemperature;
}
public void setSetTemperature(Double setTemperature) {
this.setTemperature = setTemperature;
}
public Boolean getPower() {
return power;
}
public void setPower(Boolean power) {
this.power = power;
}
public Integer getOperationMode() {
return operationMode;
}
public void setOperationMode(Integer operationMode) {
this.operationMode = operationMode;
}
public Integer getVaneHorizontal() {
return vaneHorizontal;
}
public void setVaneHorizontal(Integer vaneHorizontal) {
this.vaneHorizontal = vaneHorizontal;
}
public Integer getVaneVertical() {
return vaneVertical;
}
public void setVaneVertical(Integer vaneVertical) {
this.vaneVertical = vaneVertical;
}
public Integer getFanSpeed() {
return fanSpeed;
}
public void setFanSpeed(Integer fanSpeed) {
this.fanSpeed = fanSpeed;
}
public Integer getID() {
return iD;
}
public void setID(Integer iD) {
this.iD = iD;
}
public Integer getClient() {
return client;
}
public void setClient(Integer client) {
this.client = client;
}
public Integer getDeviceLocation() {
return deviceLocation;
}
public void setDeviceLocation(Integer deviceLocation) {
this.deviceLocation = deviceLocation;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getConfiguration() {
return configuration;
}
public void setConfiguration(String configuration) {
this.configuration = configuration;
}
public String getNumberDescription() {
return numberDescription;
}
public void setNumberDescription(String numberDescription) {
this.numberDescription = numberDescription;
}
}

View File

@@ -0,0 +1,47 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import com.google.gson.annotations.Expose;
/**
* The {@link QuantizedCoordinates} is responsible of JSON data For MELCloud API
* QuantizedCoordinates data
* Generated with jsonschema2pojo
*
* @author Luca Calcaterra - Initial contribution
*/
public class QuantizedCoordinates {
@Expose
private Double latitude;
@Expose
private Double longitude;
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
}

View File

@@ -0,0 +1,72 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import java.util.List;
import com.google.gson.annotations.Expose;
/**
* The {@link Structure} is responsible of JSON data For MELCloud API
* Structure Data
* Generated with jsonschema2pojo
*
* @author Luca Calcaterra - Initial contribution
* @author Wietse van Buitenen - Add Floor and Area
*/
public class Structure {
@Expose
private List<Floor> floors = null;
@Expose
private List<Area> areas = null;
@Expose
private List<Device> devices = null;
@Expose
private List<Object> clients = null;
public List<Floor> getFloors() {
return floors;
}
public void setFloors(List<Floor> floors) {
this.floors = floors;
}
public List<Area> getAreas() {
return areas;
}
public void setAreas(List<Area> areas) {
this.areas = areas;
}
public List<Device> getDevices() {
return devices;
}
public void setDevices(List<Device> devices) {
this.devices = devices;
}
public List<Object> getClients() {
return clients;
}
public void setClients(List<Object> clients) {
this.clients = clients;
}
}

View File

@@ -0,0 +1,146 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.api.json;
import com.google.gson.annotations.Expose;
/**
* The {@link Structure} is responsible of JSON data For MELCloud API
* WeatherObservation Data
* Generated with jsonschema2pojo
*
* @author Luca Calcaterra - Initial contribution
*/
public class WeatherObservation {
@Expose
private String date;
@Expose
private String sunrise;
@Expose
private String sunset;
@Expose
private Integer condition;
@Expose
private Integer iD;
@Expose
private Integer humidity;
@Expose
private Integer temperature;
@Expose
private String icon;
@Expose
private String conditionName;
@Expose
private Integer day;
@Expose
private Integer weatherType;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getSunrise() {
return sunrise;
}
public void setSunrise(String sunrise) {
this.sunrise = sunrise;
}
public String getSunset() {
return sunset;
}
public void setSunset(String sunset) {
this.sunset = sunset;
}
public Integer getCondition() {
return condition;
}
public void setCondition(Integer condition) {
this.condition = condition;
}
public Integer getID() {
return iD;
}
public void setID(Integer iD) {
this.iD = iD;
}
public Integer getHumidity() {
return humidity;
}
public void setHumidity(Integer humidity) {
this.humidity = humidity;
}
public Integer getTemperature() {
return temperature;
}
public void setTemperature(Integer temperature) {
this.temperature = temperature;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getConditionName() {
return conditionName;
}
public void setConditionName(String conditionName) {
this.conditionName = conditionName;
}
public Integer getDay() {
return day;
}
public void setDay(Integer day) {
this.day = day;
}
public Integer getWeatherType() {
return weatherType;
}
public void setWeatherType(Integer weatherType) {
this.weatherType = weatherType;
}
}

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.config;
/**
* Config class for a A.C. device.
*
* @author Pauli Anttila - Initial Contribution
*
*/
public class AcDeviceConfig {
public Integer deviceID;
public Integer buildingID;
public Integer pollingInterval;
@Override
public String toString() {
return "[deviceID=" + deviceID + ", buildingID=" + buildingID + ", pollingInterval=" + pollingInterval + "]";
}
}

View File

@@ -0,0 +1,38 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.config;
/**
* Config class for MELCloud account parameters.
*
* @author Pauli Anttila - Initial Contribution
*
*/
public class AccountConfig {
public String username;
public String password;
public int language;
@Override
public String toString() {
return "[username=" + username + ", password=" + getPasswordForPrinting() + ", languageId=" + language + "]";
}
private String getPasswordForPrinting() {
if (password != null) {
return password.isEmpty() ? "<empty>" : "*********";
}
return "<null>";
}
}

View File

@@ -0,0 +1,30 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.config;
/**
* Config class for a Heatpump device.
*
* @author Wietse van Buitenen - Initial Contribution
*
*/
public class HeatpumpDeviceConfig {
public Integer deviceID;
public Integer buildingID;
public Integer pollingInterval;
@Override
public String toString() {
return "[deviceID=" + deviceID + ", buildingID=" + buildingID + ", pollingInterval=" + pollingInterval + "]";
}
}

View File

@@ -0,0 +1,177 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.discovery;
import static org.openhab.binding.melcloud.internal.MelCloudBindingConstants.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
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.exceptions.MelCloudCommException;
import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
import org.openhab.binding.melcloud.internal.handler.MelCloudAccountHandler;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.osgi.service.component.annotations.Modified;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link MelCloudDiscoveryService} creates things based on the configured location.
*
* @author Luca Calcaterra - Initial Contribution
* @author Pauli Anttila - Refactoring
* @author Wietse van Buitenen - Check device type, added heatpump device
*/
public class MelCloudDiscoveryService extends AbstractDiscoveryService
implements DiscoveryService, ThingHandlerService {
private final Logger logger = LoggerFactory.getLogger(MelCloudDiscoveryService.class);
private static final int DISCOVER_TIMEOUT_SECONDS = 10;
private MelCloudAccountHandler melCloudHandler;
private ScheduledFuture<?> scanTask;
/**
* Creates a MelCloudDiscoveryService with enabled autostart.
*/
public MelCloudDiscoveryService() {
super(MelCloudBindingConstants.DISCOVERABLE_THING_TYPE_UIDS, DISCOVER_TIMEOUT_SECONDS, true);
}
@Override
protected void activate(Map<String, @Nullable Object> configProperties) {
super.activate(configProperties);
}
@Override
public void deactivate() {
super.deactivate();
}
@Override
@Modified
protected void modified(Map<String, @Nullable Object> configProperties) {
super.modified(configProperties);
}
@Override
protected void startBackgroundDiscovery() {
discoverDevices();
}
@Override
protected void startScan() {
if (this.scanTask != null) {
scanTask.cancel(true);
}
this.scanTask = scheduler.schedule(() -> discoverDevices(), 0, TimeUnit.SECONDS);
}
@Override
protected void stopScan() {
super.stopScan();
if (this.scanTask != null) {
this.scanTask.cancel(true);
this.scanTask = null;
}
}
private void discoverDevices() {
logger.debug("Discover devices");
if (melCloudHandler != null) {
try {
List<Device> deviceList = melCloudHandler.getDeviceList();
if (deviceList == null) {
logger.debug("No devices found");
} else {
ThingUID bridgeUID = melCloudHandler.getThing().getUID();
deviceList.forEach(device -> {
ThingTypeUID thingTypeUid = null;
if (device.getType() == 0) {
thingTypeUid = THING_TYPE_ACDEVICE;
} else if (device.getType() == 1) {
thingTypeUid = THING_TYPE_HEATPUMPDEVICE;
} else {
logger.debug("Unsupported device found: name {} : type: {}", device.getDeviceName(),
device.getType());
return;
}
ThingUID deviceThing = new ThingUID(thingTypeUid, melCloudHandler.getThing().getUID(),
device.getDeviceID().toString());
Map<String, Object> deviceProperties = new HashMap<>();
deviceProperties.put("deviceID", device.getDeviceID().toString());
deviceProperties.put("serialNumber", device.getSerialNumber().toString());
deviceProperties.put("macAddress", device.getMacAddress().toString());
deviceProperties.put("deviceName", device.getDeviceName().toString());
deviceProperties.put("buildingID", device.getBuildingID().toString());
String label = createLabel(device);
logger.debug("Found device: {} : {}", label, deviceProperties);
thingDiscovered(DiscoveryResultBuilder.create(deviceThing).withLabel(label)
.withProperties(deviceProperties)
.withRepresentationProperty(device.getDeviceID().toString()).withBridge(bridgeUID)
.build());
});
}
} catch (MelCloudLoginException e) {
logger.debug("Login error occurred during device list fetch, reason {}. ", e.getMessage(), e);
} catch (MelCloudCommException e) {
logger.debug("Error occurred during device list fetch, reason {}. ", e.getMessage(), e);
}
}
}
private String createLabel(Device device) {
StringBuilder sb = new StringBuilder();
if (device.getType() == 0) {
sb.append("A.C. Device - ");
} else if (device.getType() == 1) {
sb.append("Heatpump Device - ");
}
if (device.getBuildingName() != null && device.getBuildingName() instanceof String) {
sb.append(device.getBuildingName()).append(" - ");
}
sb.append(device.getDeviceName());
return sb.toString();
}
@Override
public void setThingHandler(@Nullable ThingHandler handler) {
if (handler instanceof MelCloudAccountHandler) {
melCloudHandler = (MelCloudAccountHandler) handler;
}
}
@Override
public @Nullable ThingHandler getThingHandler() {
return melCloudHandler;
}
}

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.exceptions;
/**
* Exception to encapsulate any issues communicating with MELCloud.
*
* @author Pauli Anttila - Initial Contribution
*/
public class MelCloudCommException extends Exception {
private static final long serialVersionUID = 1L;
public MelCloudCommException(Throwable cause) {
super("Error occurred when communicating with MELCloud", cause);
}
public MelCloudCommException(String message) {
super(message);
}
public MelCloudCommException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.exceptions;
/**
* Exception to encapsulate any login issues with MELCloud.
*
* @author Pauli Anttila - Initial Contribution
*/
public class MelCloudLoginException extends Exception {
private static final long serialVersionUID = 1L;
public MelCloudLoginException(Throwable cause) {
super("Error occurred during login to MELCloud", cause);
}
public MelCloudLoginException(String message) {
super(message);
}
public MelCloudLoginException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,222 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.handler;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
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.config.AccountConfig;
import org.openhab.binding.melcloud.internal.discovery.MelCloudDiscoveryService;
import org.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.BaseBridgeHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link MelCloudAccountHandler} is the handler for MELCloud API and connects it
* to the webservice.
*
* @author Luca Calcaterra - Initial contribution
* @author Pauli Anttila - Refactoring
* @author Wietse van Buitenen - Return all devices, added heatpump device
*/
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;
public MelCloudAccountHandler(Bridge bridge) {
super(bridge);
}
@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Collections.singleton(MelCloudDiscoveryService.class);
}
@Override
public void initialize() {
logger.debug("Initializing MELCloud account handler.");
config = getConfigAs(AccountConfig.class);
connection = new MelCloudConnection();
devices = Collections.emptyList();
loginCredentialError = false;
startConnectionCheck();
}
@Override
public void dispose() {
logger.debug("Running dispose()");
stopConnectionCheck();
connection = null;
devices = Collections.emptyList();
config = null;
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
}
public ThingUID getID() {
return getThing().getUID();
}
public List<Device> getDeviceList() throws MelCloudCommException, MelCloudLoginException {
connectIfNotConnected();
return connection.fetchDeviceList();
}
private void connect() throws MelCloudCommException, MelCloudLoginException {
if (loginCredentialError) {
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);
devices = connection.fetchDeviceList();
updateStatus(ThingStatus.ONLINE);
} catch (MelCloudLoginException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
loginCredentialError = true;
throw e;
} catch (MelCloudCommException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
throw e;
}
}
private synchronized void connectIfNotConnected() throws MelCloudCommException, MelCloudLoginException {
if (!isConnected()) {
connect();
}
}
public boolean isConnected() {
return connection.isConnected();
}
public DeviceStatus sendDeviceStatus(DeviceStatus deviceStatus)
throws MelCloudCommException, MelCloudLoginException {
connectIfNotConnected();
try {
return connection.sendDeviceStatus(deviceStatus);
} catch (MelCloudCommException e) {
logger.debug("Sending failed, retry once with relogin");
connect();
return connection.sendDeviceStatus(deviceStatus);
}
}
public DeviceStatus fetchDeviceStatus(int deviceId, Optional<Integer> buildingId)
throws MelCloudCommException, MelCloudLoginException {
connectIfNotConnected();
int bid = buildingId.orElse(findBuildingId(deviceId));
try {
return connection.fetchDeviceStatus(deviceId, bid);
} catch (MelCloudCommException e) {
logger.debug("Sending failed, retry once with relogin");
connect();
return connection.fetchDeviceStatus(deviceId, bid);
}
}
public HeatpumpDeviceStatus sendHeatpumpDeviceStatus(HeatpumpDeviceStatus heatpumpDeviceStatus)
throws MelCloudCommException, MelCloudLoginException {
connectIfNotConnected();
try {
return connection.sendHeatpumpDeviceStatus(heatpumpDeviceStatus);
} catch (MelCloudCommException e) {
logger.debug("Sending failed, retry once with relogin");
connect();
return connection.sendHeatpumpDeviceStatus(heatpumpDeviceStatus);
}
}
public HeatpumpDeviceStatus fetchHeatpumpDeviceStatus(int deviceId, Optional<Integer> buildingId)
throws MelCloudCommException, MelCloudLoginException {
connectIfNotConnected();
int bid = buildingId.orElse(findBuildingId(deviceId));
try {
return connection.fetchHeatpumpDeviceStatus(deviceId, bid);
} catch (MelCloudCommException e) {
logger.debug("Sending failed, retry once with relogin");
connect();
return connection.fetchHeatpumpDeviceStatus(deviceId, bid);
}
}
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));
}
private void startConnectionCheck() {
if (connectionCheckTask == null || connectionCheckTask.isCancelled()) {
logger.debug("Start periodic connection check");
Runnable runnable = () -> {
logger.debug("Check MELCloud connection");
if (connection.isConnected()) {
logger.debug("Connection to MELCloud open");
} else {
try {
connect();
} catch (MelCloudLoginException e) {
logger.debug("Connection to MELCloud down due to login error, reason: {}.", e.getMessage());
} catch (MelCloudCommException e) {
logger.debug("Connection to MELCloud down, reason: {}.", e.getMessage());
} catch (RuntimeException e) {
logger.warn("Unknown error occurred during connection check, reason: {}.", e.getMessage(), e);
}
}
};
connectionCheckTask = scheduler.scheduleWithFixedDelay(runnable, 0, 60, TimeUnit.SECONDS);
} else {
logger.debug("Connection check task already running");
}
}
private void stopConnectionCheck() {
if (connectionCheckTask != null) {
logger.debug("Stop periodic connection check");
connectionCheckTask.cancel(true);
connectionCheckTask = null;
}
}
}

View File

@@ -0,0 +1,310 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.handler;
import static org.openhab.binding.melcloud.internal.MelCloudBindingConstants.*;
import static org.openhab.core.library.unit.SIUnits.CELSIUS;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
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.openhab.binding.melcloud.internal.config.AcDeviceConfig;
import org.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
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.ThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link MelCloudDeviceHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Luca Calcaterra - Initial contribution
* @author Pauli Anttila - Refactoring
*/
public class MelCloudDeviceHandler extends BaseThingHandler {
private static final int EFFECTIVE_FLAG_POWER = 0x01;
private static final int EFFECTIVE_FLAG_OPERATION_MODE = 0x02;
private static final int EFFECTIVE_FLAG_TEMPERATURE = 0x04;
private static final int EFFECTIVE_FLAG_FAN_SPEED = 0x08;
private static final int EFFECTIVE_FLAG_VANE_VERTICAL = 0x10;
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;
public MelCloudDeviceHandler(Thing thing) {
super(thing);
}
@Override
public void initialize() {
logger.debug("Initializing {} handler.", getThing().getThingTypeUID());
Bridge bridge = getBridge();
if (bridge == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge Not set");
return;
}
config = getConfigAs(AcDeviceConfig.class);
logger.debug("A.C. device config: {}", config);
initializeBridge(bridge.getHandler(), bridge.getStatus());
}
@Override
public void dispose() {
logger.debug("Running dispose()");
if (refreshTask != null) {
refreshTask.cancel(true);
refreshTask = null;
}
melCloudHandler = null;
}
@Override
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
logger.debug("bridgeStatusChanged {} for thing {}", bridgeStatusInfo, getThing().getUID());
Bridge bridge = getBridge();
if (bridge != null) {
initializeBridge(bridge.getHandler(), 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;
if (bridgeStatus == ThingStatus.ONLINE) {
updateStatus(ThingStatus.ONLINE);
startAutomaticRefresh();
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
} else {
updateStatus(ThingStatus.OFFLINE);
}
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Received command '{}' to channel {}", command, channelUID);
if (command instanceof RefreshType) {
logger.debug("Refresh command not supported");
return;
}
if (melCloudHandler == null) {
logger.warn("No connection to MELCloud available, ignoring command");
return;
}
if (deviceStatus == null) {
logger.info("No initial data available, bridge is probably offline. Ignoring command");
return;
}
DeviceStatus cmdtoSend = getDeviceStatusCopy(deviceStatus);
cmdtoSend.setEffectiveFlags(0);
switch (channelUID.getId()) {
case CHANNEL_POWER:
cmdtoSend.setPower(command == OnOffType.ON);
cmdtoSend.setEffectiveFlags(EFFECTIVE_FLAG_POWER);
break;
case CHANNEL_OPERATION_MODE:
cmdtoSend.setOperationMode(Integer.parseInt(command.toString()));
cmdtoSend.setEffectiveFlags(EFFECTIVE_FLAG_OPERATION_MODE);
break;
case CHANNEL_SET_TEMPERATURE:
BigDecimal val = null;
if (command instanceof QuantityType) {
QuantityType<Temperature> quantity = new QuantityType<Temperature>(command.toString())
.toUnit(CELSIUS);
if (quantity != null) {
val = quantity.toBigDecimal().setScale(1, RoundingMode.HALF_UP);
// round nearest .5
double v = Math.round(val.doubleValue() * 2) / 2.0;
cmdtoSend.setSetTemperature(v);
cmdtoSend.setEffectiveFlags(EFFECTIVE_FLAG_TEMPERATURE);
}
}
if (val == null) {
logger.debug("Can't convert '{}' to set temperature", command);
}
break;
case CHANNEL_FAN_SPEED:
cmdtoSend.setSetFanSpeed(Integer.parseInt(command.toString()));
cmdtoSend.setEffectiveFlags(EFFECTIVE_FLAG_FAN_SPEED);
break;
case CHANNEL_VANE_VERTICAL:
cmdtoSend.setVaneVertical(Integer.parseInt(command.toString()));
cmdtoSend.setEffectiveFlags(EFFECTIVE_FLAG_VANE_VERTICAL);
break;
case CHANNEL_VANE_HORIZONTAL:
cmdtoSend.setVaneHorizontal(Integer.parseInt(command.toString()));
cmdtoSend.setEffectiveFlags(EFFECTIVE_FLAG_VANE_HORIZONTAL);
break;
default:
logger.debug("Read-only or unknown channel {}, skipping update", channelUID);
}
if (cmdtoSend.getEffectiveFlags() > 0) {
cmdtoSend.setHasPendingCommand(true);
cmdtoSend.setDeviceID(config.deviceID);
try {
DeviceStatus newDeviceStatus = melCloudHandler.sendDeviceStatus(cmdtoSend);
updateChannels(newDeviceStatus);
} catch (MelCloudLoginException e) {
logger.warn("Command '{}' to channel '{}' failed due to login error, reason {}. ", command, channelUID,
e.getMessage(), e);
} catch (MelCloudCommException e) {
logger.warn("Command '{}' to channel '{}' failed, reason {}. ", command, channelUID, e.getMessage(), e);
}
} else {
logger.debug("Nothing to send");
}
}
private DeviceStatus getDeviceStatusCopy(DeviceStatus deviceStatus) {
DeviceStatus copy = new DeviceStatus();
synchronized (this) {
copy.setPower(deviceStatus.getPower());
copy.setOperationMode(deviceStatus.getOperationMode());
copy.setSetTemperature(deviceStatus.getSetTemperature());
copy.setSetFanSpeed(deviceStatus.getSetFanSpeed());
copy.setVaneVertical(deviceStatus.getVaneVertical());
copy.setVaneHorizontal(deviceStatus.getVaneHorizontal());
copy.setEffectiveFlags(deviceStatus.getEffectiveFlags());
copy.setHasPendingCommand(deviceStatus.getHasPendingCommand());
copy.setDeviceID(deviceStatus.getDeviceID());
}
return copy;
}
private void startAutomaticRefresh() {
if (refreshTask == null || refreshTask.isCancelled()) {
refreshTask = scheduler.scheduleWithFixedDelay(this::getDeviceDataAndUpdateChannels, 1,
config.pollingInterval, TimeUnit.SECONDS);
}
}
private void getDeviceDataAndUpdateChannels() {
if (melCloudHandler.isConnected()) {
logger.debug("Update device '{}' channels", getThing().getThingTypeUID());
try {
DeviceStatus newDeviceStatus = melCloudHandler.fetchDeviceStatus(config.deviceID,
Optional.ofNullable(config.buildingID));
updateChannels(newDeviceStatus);
} catch (MelCloudLoginException e) {
logger.debug("Login error occurred during device '{}' polling, reason {}. ",
getThing().getThingTypeUID(), e.getMessage(), e);
} catch (MelCloudCommException e) {
logger.debug("Error occurred during device '{}' polling, reason {}. ", getThing().getThingTypeUID(),
e.getMessage(), e);
}
} else {
logger.debug("Connection to MELCloud is not open, skipping periodic update");
}
}
private synchronized void updateChannels(DeviceStatus newDeviceStatus) {
deviceStatus = newDeviceStatus;
for (Channel channel : getThing().getChannels()) {
updateChannels(channel.getUID().getId(), deviceStatus);
}
}
private void updateChannels(String channelId, DeviceStatus deviceStatus) {
switch (channelId) {
case CHANNEL_POWER:
updateState(CHANNEL_POWER, deviceStatus.getPower() ? OnOffType.ON : OnOffType.OFF);
break;
case CHANNEL_OPERATION_MODE:
updateState(CHANNEL_OPERATION_MODE, new StringType(deviceStatus.getOperationMode().toString()));
break;
case CHANNEL_SET_TEMPERATURE:
updateState(CHANNEL_SET_TEMPERATURE,
new QuantityType<>(deviceStatus.getSetTemperature(), SIUnits.CELSIUS));
break;
case CHANNEL_FAN_SPEED:
updateState(CHANNEL_FAN_SPEED, new StringType(deviceStatus.getSetFanSpeed().toString()));
break;
case CHANNEL_VANE_HORIZONTAL:
updateState(CHANNEL_VANE_HORIZONTAL, new StringType(deviceStatus.getVaneHorizontal().toString()));
break;
case CHANNEL_VANE_VERTICAL:
updateState(CHANNEL_VANE_VERTICAL, new StringType(deviceStatus.getVaneVertical().toString()));
break;
case CHANNEL_OFFLINE:
updateState(CHANNEL_OFFLINE, deviceStatus.getOffline() ? OnOffType.ON : OnOffType.OFF);
break;
case CHANNEL_HAS_PENDING_COMMAND:
updateState(CHANNEL_HAS_PENDING_COMMAND,
deviceStatus.getHasPendingCommand() ? OnOffType.ON : OnOffType.OFF);
break;
case CHANNEL_ROOM_TEMPERATURE:
updateState(CHANNEL_ROOM_TEMPERATURE, new DecimalType(deviceStatus.getRoomTemperature()));
break;
case CHANNEL_LAST_COMMUNICATION:
updateState(CHANNEL_LAST_COMMUNICATION,
new DateTimeType(convertDateTime(deviceStatus.getLastCommunication())));
break;
case CHANNEL_NEXT_COMMUNICATION:
updateState(CHANNEL_NEXT_COMMUNICATION,
new DateTimeType(convertDateTime(deviceStatus.getNextCommunication())));
break;
}
}
private ZonedDateTime convertDateTime(String dateTime) {
return ZonedDateTime.ofInstant(LocalDateTime.parse(dateTime, DateTimeFormatter.ISO_LOCAL_DATE_TIME),
ZoneOffset.UTC, ZoneId.systemDefault());
}
}

View File

@@ -0,0 +1,285 @@
/**
* Copyright (c) 2010-2020 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.melcloud.internal.handler;
import static org.openhab.binding.melcloud.internal.MelCloudBindingConstants.*;
import static org.openhab.core.library.unit.SIUnits.CELSIUS;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
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.openhab.binding.melcloud.internal.config.HeatpumpDeviceConfig;
import org.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
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.ThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link MelCloudHeatpumpDeviceHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Wietse van Buitenen - Initial contribution
*/
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;
public MelCloudHeatpumpDeviceHandler(Thing thing) {
super(thing);
}
@Override
public void initialize() {
logger.debug("Initializing {} handler.", getThing().getThingTypeUID());
Bridge bridge = getBridge();
if (bridge == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge Not set");
return;
}
config = getConfigAs(HeatpumpDeviceConfig.class);
logger.debug("Heatpump device config: {}", config);
initializeBridge(bridge.getHandler(), bridge.getStatus());
}
@Override
public void dispose() {
logger.debug("Running dispose()");
if (refreshTask != null) {
refreshTask.cancel(true);
refreshTask = null;
}
melCloudHandler = null;
}
@Override
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
logger.debug("bridgeStatusChanged {} for thing {}", bridgeStatusInfo, getThing().getUID());
Bridge bridge = getBridge();
if (bridge != null) {
initializeBridge(bridge.getHandler(), 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;
if (bridgeStatus == ThingStatus.ONLINE) {
updateStatus(ThingStatus.ONLINE);
startAutomaticRefresh();
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
} else {
updateStatus(ThingStatus.OFFLINE);
}
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Received command '{}' to channel {}", command, channelUID);
if (command instanceof RefreshType) {
logger.debug("Refresh command not supported");
return;
}
if (melCloudHandler == null) {
logger.warn("No connection to MELCloud available, ignoring command");
return;
}
if (heatpumpDeviceStatus == null) {
logger.info("No initial data available, bridge is probably offline. Ignoring command");
return;
}
HeatpumpDeviceStatus cmdtoSend = getHeatpumpDeviceStatusCopy(heatpumpDeviceStatus);
cmdtoSend.setEffectiveFlags(0L);
switch (channelUID.getId()) {
case CHANNEL_POWER:
cmdtoSend.setPower(command == OnOffType.ON);
cmdtoSend.setEffectiveFlags(EFFECTIVE_FLAG_POWER);
break;
case CHANNEL_SET_TEMPERATURE_ZONE1:
BigDecimal val = null;
if (command instanceof QuantityType) {
QuantityType<Temperature> quantity = new QuantityType<Temperature>(command.toString())
.toUnit(CELSIUS);
if (quantity != null) {
val = quantity.toBigDecimal().setScale(1, RoundingMode.HALF_UP);
// round nearest .5
double v = Math.round(val.doubleValue() * 2) / 2.0;
cmdtoSend.setSetTemperatureZone1(v);
cmdtoSend.setEffectiveFlags(EFFECTIVE_FLAG_TEMPERATURE_ZONE1);
}
}
if (val == null) {
logger.debug("Can't convert '{}' to set temperature", command);
}
break;
case CHANNEL_FORCED_HOTWATERMODE:
cmdtoSend.setForcedHotWaterMode(command == OnOffType.ON);
cmdtoSend.setEffectiveFlags(EFFECTIVE_FLAG_HOTWATER);
break;
default:
logger.debug("Read-only or unknown channel {}, skipping update", channelUID);
}
if (cmdtoSend.getEffectiveFlags() > 0) {
cmdtoSend.setHasPendingCommand(true);
cmdtoSend.setDeviceID(config.deviceID);
try {
HeatpumpDeviceStatus newHeatpumpDeviceStatus = melCloudHandler.sendHeatpumpDeviceStatus(cmdtoSend);
updateChannels(newHeatpumpDeviceStatus);
} catch (MelCloudLoginException e) {
logger.warn("Command '{}' to channel '{}' failed due to login error, reason {}. ", command, channelUID,
e.getMessage(), e);
} catch (MelCloudCommException e) {
logger.warn("Command '{}' to channel '{}' failed, reason {}. ", command, channelUID, e.getMessage(), e);
}
} else {
logger.debug("Nothing to send");
}
}
private HeatpumpDeviceStatus getHeatpumpDeviceStatusCopy(HeatpumpDeviceStatus heatpumpDeviceStatus) {
HeatpumpDeviceStatus copy = new HeatpumpDeviceStatus();
synchronized (this) {
copy.setDeviceID(heatpumpDeviceStatus.getDeviceID());
copy.setEffectiveFlags(heatpumpDeviceStatus.getEffectiveFlags());
copy.setPower(heatpumpDeviceStatus.getPower());
copy.setSetTemperatureZone1(heatpumpDeviceStatus.getSetTemperatureZone1());
copy.setForcedHotWaterMode(heatpumpDeviceStatus.getForcedHotWaterMode());
copy.setHasPendingCommand(heatpumpDeviceStatus.getHasPendingCommand());
}
return copy;
}
private void startAutomaticRefresh() {
if (refreshTask == null || refreshTask.isCancelled()) {
refreshTask = scheduler.scheduleWithFixedDelay(this::getDeviceDataAndUpdateChannels, 1,
config.pollingInterval, TimeUnit.SECONDS);
}
}
private void getDeviceDataAndUpdateChannels() {
if (melCloudHandler.isConnected()) {
logger.debug("Update device '{}' channels", getThing().getThingTypeUID());
try {
HeatpumpDeviceStatus newHeatpumpDeviceStatus = melCloudHandler
.fetchHeatpumpDeviceStatus(config.deviceID, Optional.ofNullable(config.buildingID));
updateChannels(newHeatpumpDeviceStatus);
} catch (MelCloudLoginException e) {
logger.debug("Login error occurred during device '{}' polling, reason {}. ",
getThing().getThingTypeUID(), e.getMessage(), e);
} catch (MelCloudCommException e) {
logger.debug("Error occurred during device '{}' polling, reason {}. ", getThing().getThingTypeUID(),
e.getMessage(), e);
}
} else {
logger.debug("Connection to MELCloud is not open, skipping periodic update");
}
}
private synchronized void updateChannels(HeatpumpDeviceStatus newHeatpumpDeviceStatus) {
heatpumpDeviceStatus = newHeatpumpDeviceStatus;
for (Channel channel : getThing().getChannels()) {
updateChannels(channel.getUID().getId(), heatpumpDeviceStatus);
}
}
private void updateChannels(String channelId, HeatpumpDeviceStatus heatpumpDeviceStatus) {
switch (channelId) {
case CHANNEL_POWER:
updateState(CHANNEL_POWER, heatpumpDeviceStatus.getPower() ? OnOffType.ON : OnOffType.OFF);
break;
case CHANNEL_TANKWATERTEMPERATURE:
updateState(CHANNEL_TANKWATERTEMPERATURE,
new DecimalType(heatpumpDeviceStatus.getTankWaterTemperature()));
break;
case CHANNEL_SET_TEMPERATURE_ZONE1:
updateState(CHANNEL_SET_TEMPERATURE_ZONE1,
new QuantityType<>(heatpumpDeviceStatus.getSetTemperatureZone1(), SIUnits.CELSIUS));
break;
case CHANNEL_ROOM_TEMPERATURE_ZONE1:
updateState(CHANNEL_ROOM_TEMPERATURE_ZONE1,
new DecimalType(heatpumpDeviceStatus.getRoomTemperatureZone1()));
break;
case CHANNEL_FORCED_HOTWATERMODE:
updateState(CHANNEL_FORCED_HOTWATERMODE,
heatpumpDeviceStatus.getForcedHotWaterMode() ? OnOffType.ON : OnOffType.OFF);
break;
case CHANNEL_LAST_COMMUNICATION:
updateState(CHANNEL_LAST_COMMUNICATION,
new DateTimeType(convertDateTime(heatpumpDeviceStatus.getLastCommunication())));
break;
case CHANNEL_NEXT_COMMUNICATION:
updateState(CHANNEL_NEXT_COMMUNICATION,
new DateTimeType(convertDateTime(heatpumpDeviceStatus.getNextCommunication())));
break;
case CHANNEL_HAS_PENDING_COMMAND:
updateState(CHANNEL_HAS_PENDING_COMMAND,
heatpumpDeviceStatus.getHasPendingCommand() ? OnOffType.ON : OnOffType.OFF);
break;
case CHANNEL_OFFLINE:
updateState(CHANNEL_OFFLINE, heatpumpDeviceStatus.getOffline() ? OnOffType.ON : OnOffType.OFF);
break;
}
}
private ZonedDateTime convertDateTime(String dateTime) {
return ZonedDateTime.ofInstant(LocalDateTime.parse(dateTime, DateTimeFormatter.ISO_LOCAL_DATE_TIME),
ZoneOffset.UTC, ZoneId.systemDefault());
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="melcloud" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>MELCloud Binding</name>
<description>Binding for Mitsubishi MELCloud connected A.C. devices.</description>
<author>Luca Calcaterra, Pauli Anttila, Wietse van Buitenen</author>
</binding:binding>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="melcloud"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="acdevice">
<supported-bridge-type-refs>
<bridge-type-ref id="melcloudaccount"/>
</supported-bridge-type-refs>
<label>A.C. Device</label>
<description>Air conditioning device</description>
<channels>
<channel id="hasPendingCommand" typeId="hasPendingCommand-channel"/>
<channel id="offline" typeId="offline-channel"/>
<channel id="power" typeId="power-channel"/>
<channel id="operationMode" typeId="operationMode-channel"/>
<channel id="setTemperature" typeId="setTemperature-channel"/>
<channel id="fanSpeed" typeId="fanSpeed-channel"/>
<channel id="vaneHorizontal" typeId="vaneHorizontal-channel"/>
<channel id="vaneVertical" typeId="vaneVertical-channel"/>
<channel id="roomTemperature" typeId="roomTemperature-channel"/>
<channel id="lastCommunication" typeId="lastCommunication-channel"/>
<channel id="nextCommunication" typeId="nextCommunication-channel"/>
</channels>
<config-description>
<parameter name="deviceID" type="integer" required="true">
<label>Device ID</label>
<description>Device ID of the A.C. device</description>
</parameter>
<parameter name="buildingID" type="integer">
<label>Building ID</label>
<description>Building ID of the A.C. device.</description>
</parameter>
<parameter name="pollingInterval" type="integer" required="true">
<label>Polling Interval</label>
<description>Time interval how often poll data from MELCloud</description>
<default>60</default>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="melcloud"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<!-- Common channels -->
<channel-type id="power-channel">
<item-type>Switch</item-type>
<label>Power</label>
<description>Power status of device</description>
</channel-type>
<channel-type id="hasPendingCommand-channel">
<item-type>Switch</item-type>
<label>Pending Command</label>
<description>Device has a pending command(s)</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="offline-channel">
<item-type>Switch</item-type>
<label>Is Offline</label>
<description>Is device in offline state.</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="lastCommunication-channel">
<item-type>DateTime</item-type>
<label>Last Communication</label>
<description>Last communication time between device and MELCloud</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="nextCommunication-channel">
<item-type>DateTime</item-type>
<label>Next Communication</label>
<description>Next communication time between device and MELCloud</description>
<state readOnly="true"/>
</channel-type>
<!-- A.C. Device Channels -->
<channel-type id="operationMode-channel">
<item-type>String</item-type>
<label>Operation Mode</label>
<description>Operation mode</description>
<state readOnly="false">
<options>
<option value="1">Heat</option>
<option value="2">Dry</option>
<option value="3">Cool</option>
<option value="7">Fan</option>
<option value="8">Auto</option>
</options>
</state>
</channel-type>
<channel-type id="setTemperature-channel">
<item-type>Number:Temperature</item-type>
<label>Set Temperature</label>
<description>Set temperature</description>
<state min="10" max="40" step="0.5" pattern="%.1f %unit%" readOnly="false"/>
</channel-type>
<channel-type id="fanSpeed-channel">
<item-type>String</item-type>
<label>Fan Speed</label>
<description>Fan speed</description>
<state readOnly="false">
<options>
<option value="0">Auto</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</options>
</state>
</channel-type>
<channel-type id="vaneHorizontal-channel">
<item-type>String</item-type>
<label>Vane Horizontal</label>
<description>Vane horizontal</description>
<state readOnly="false">
<options>
<option value="0">Auto</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="12">Swing</option>
</options>
</state>
</channel-type>
<channel-type id="vaneVertical-channel">
<item-type>String</item-type>
<label>Vane Vertical</label>
<description>Vane vertical</description>
<state readOnly="false">
<options>
<option value="0">Auto</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="7">Swing</option>
</options>
</state>
</channel-type>
<channel-type id="roomTemperature-channel">
<item-type>Number:Temperature</item-type>
<label>Room Temperature</label>
<description>Room temperature</description>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<!-- Heatpump Device Channels -->
<channel-type id="tankWaterTemperature-channel">
<item-type>Number:Temperature</item-type>
<label>Tank Temperature</label>
<description>Temperature of water i</description>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="forcedHotWaterMode-channel">
<item-type>Switch</item-type>
<label>Forced Hot Water Mode</label>
<description>If water mode is Heat Now (true) or Auto (false)</description>
</channel-type>
<channel-type id="roomTemperatureZone1-channel">
<item-type>Number:Temperature</item-type>
<label>Room Temperature Zone 1</label>
<description>Room temperature for zone 1</description>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="setTemperatureZone1-channel">
<item-type>Number:Temperature</item-type>
<label>Set Temperature Zone 1</label>
<description>Set temperature for zone 1</description>
<state min="10" max="30" step="0.5" pattern="%.1f %unit%" readOnly="false"/>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="melcloud"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="heatpumpdevice">
<supported-bridge-type-refs>
<bridge-type-ref id="melcloudaccount"/>
</supported-bridge-type-refs>
<label>Heatpump Device</label>
<description>Heatpump device</description>
<channels>
<channel id="power" typeId="power-channel"/>
<channel id="tankWaterTemperature" typeId="tankWaterTemperature-channel"/>
<channel id="forcedHotWaterMode" typeId="forcedHotWaterMode-channel"/>
<channel id="roomTemperatureZone1" typeId="roomTemperatureZone1-channel"/>
<channel id="setTemperatureZone1" typeId="setTemperatureZone1-channel"/>
<channel id="hasPendingCommand" typeId="hasPendingCommand-channel"/>
<channel id="offline" typeId="offline-channel"/>
<channel id="lastCommunication" typeId="lastCommunication-channel"/>
<channel id="nextCommunication" typeId="nextCommunication-channel"/>
</channels>
<config-description>
<parameter name="deviceID" type="integer" required="true">
<label>Device ID</label>
<description>Device ID of the Heatpump device</description>
</parameter>
<parameter name="buildingID" type="integer">
<label>Building ID</label>
<description>Building ID of the Heatpump device.</description>
</parameter>
<parameter name="pollingInterval" type="integer" required="true">
<label>Polling Interval</label>
<description>Time interval how often poll data from MELCloud</description>
<default>60</default>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="melcloud"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<bridge-type id="melcloudaccount">
<label>MELCloud Account</label>
<description>MELCloud cloud service account</description>
<config-description>
<parameter name="username" type="text" required="true">
<label>Username</label>
<description>MELCloud email address</description>
</parameter>
<parameter name="password" type="text" required="true">
<context>password</context>
<label>Password</label>
<description>MELCloud password</description>
</parameter>
<parameter name="language" type="text" required="true">
<label>Language</label>
<description>Language</description>
<options>
<option value="0">English</option>
<option value="1">Bulgarian</option>
<option value="2">Czech</option>
<option value="3">Danish</option>
<option value="4">German</option>
<option value="5">Estonian</option>
<option value="6">Spanish</option>
<option value="7">French</option>
<option value="8">Armenian</option>
<option value="9">Latvian</option>
<option value="10">Lithuanian</option>
<option value="11">Hungarian</option>
<option value="12">Dutch</option>
<option value="13">Norwegian</option>
<option value="14">Polish</option>
<option value="15">Portuguese</option>
<option value="16">Russian</option>
<option value="17">Finnish</option>
<option value="18">Swedish</option>
<option value="19">Italian</option>
<option value="20">Ukrainian</option>
<option value="21">Turkish</option>
<option value="22">Greek</option>
<option value="23">Croatian</option>
<option value="24">Romanian</option>
<option value="25">Slovenian</option>
</options>
<default>0</default>
</parameter>
</config-description>
</bridge-type>
</thing:thing-descriptions>