Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[intesis] - added IntesisBox support #8694

Merged
merged 8 commits into from
Oct 24, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 29 additions & 25 deletions bundles/org.openhab.binding.intesis/README.md
Original file line number Diff line number Diff line change
@@ -1,62 +1,67 @@
# Intesis Binding

This binding connects to WiFi [IntesisHome](http://www.intesishome.com/) devices using their local REST Api.
It does actually not support [IntesisBox](http://www.intesisbox.com/) devices but support is planned in upcoming version.
This binding connects to WiFi [IntesisHome](https://www.intesis.com/products/cloud-solutions/ac-cloud-control) devices using their local REST Api and to [IntesisBox](https://www.intesis.com/products/ac-interfaces/wifi-gateways) devices using TCP connection.



## Supported Things

This binding only supports one thing type:

| Thing | Thing Type | Description |
|------------ |------------|---------------------------------|
| intesisHome | Thing | Represents a single WiFi device |
| Thing | Thing Type | Description |
|-------------|------------|---------------------------------------------|
| intesisHome | Thing | Represents a single IntesisHome WiFi device |
| intesisBox | Thing | Represents a single IntesisBox WiFi device |

## Discovery

Intesis devices do not support auto discovery.

## Thing Configuration

The binding needs two configuration parameters.
The binding uses the following configuration parameters.

| Parameter | Description |
|-----------|---------------------------------------------------|
| ipAddress | IP-Address of the device |
| password | Password to login to the local webserver of device |
| Parameter | Valid for ThingType | Description |
|-----------|---------------------|----------------------------------------------------------------|
| ipAddress | Both | IP-Address of the device |
| password | IntesisHome | Password to login to the local webserver of IntesisHome device |
| port | IntesisBox | TCP port to connect to IntesisBox device, defaults to 3310 |


## Channels

| Channel ID | Item Type | Description | Possible Values |
|--------------------|--------------------|---------------------------------------------|---------------------------|
| power | Switch | Turns power on/off for your climate system. | ON, OFF |
| mode | String | The heating/cooling mode. | AUTO,HEAT,DRY,FAN,COOL |
| fanSpeed | String | Fan speed (if applicable) | AUTO,1-10 |
| vanesUpDown | String | Control of up/down vanes (if applicable) | AUTO,1-9,SWING,SWIRL,WIDE |
| vanesUpDown | String | Control of left/right vanes (if applicable) | AUTO,1-9,SWING,SWIRL,WIDE |
| targetTemperature | Number:Temperature | The currently set target temperature. | |
| ambientTemperature | Number:Temperature | (Readonly) The ambient air temperature. | |
| outdoorTemperature | Number:Temperature | (Readonly) The outdoor air temperature. | |
| Channel ID | Item Type | Description | Possible Values |
|--------------------|--------------------|--------------------------------------------------------|-----------------------------|
| power | Switch | Turns power on/off for your climate system. | ON,OFF |
| mode | String | The heating/cooling mode. | AUTO,HEAT,DRY,FAN,COOL |
| fanSpeed | String | Fan speed (if applicable) | AUTO,1-10 |
| vanesUpDown | String | Control of up/down vanes (if applicable) | AUTO,1-9,SWING,SWIRL,WIDE |
| vanesUpDown | String | Control of left/right vanes (if applicable) | AUTO,1-9,SWING,SWIRL,WIDE |
| targetTemperature | Number:Temperature | The currently set target temperature (if applicable) | range between 18°C and 30°C |
| ambientTemperature | Number:Temperature | (Readonly) The ambient air temperature (if applicable) | |
| outdoorTemperature | Number:Temperature | (Readonly) The outdoor air temperature (if applicable) | |
| errorStatus | String | (Readonly) The error status of the device | OK,ERR |
| errorCode | String | (Readonly) The error code if an error encountered | not documented |

Note that individual A/C units may not support all channels, or all possible values for those channels.

The binding will add all supported channels and possible values on first thing initialization and list them as thing properties.
If new channels or values might be supported after firmware upgrades, deleting the thing and reading is necessary.
For example, not all A/C units have controllable vanes. Or fan speed may be limited to 1-4, instead of all of 1-9.
The set point temperature is also limited to a device specific range. For set point temperature, sending an invalid value
If new channels or values might be supported after firmware upgrades, deleting the thing and re-adding is necessary.
For example, not all A/C units have controllable vanes or fan speed may be limited to 1-4, instead of all of 1-9.
The target temperature is also limited to a device specific range. For target temperature, sending an invalid value
will cause it to choose the minimum/maximum allowable value as appropriate. The device will also round it to
whatever step size it supports. For all other channels, invalid values are ignored.
IntesisBox firmware 1.3.3 reports temperatures by full degrees only (e.g. 23.0) even if a half degree (e.g. 23.5) was set.

## Full Example

The binding can be fully setup from the UI but if you decide to use files here is a full example:

**Things**

```intesisHome.things
```
Thing intesis:intesisHome:acOffice "AC Unit Adapter" @ "AC" [ipAddress="192.168.1.100", password="xxxxx"]
Thing intesis:intesisBox:acOffice "AC Unit Adapter" @ "AC" [ipAddress="192.168.1.100", port=3310]
```

**Items**
Expand Down Expand Up @@ -89,4 +94,3 @@ sitemap intesishome label="My AC control" {
}
}
```

Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class IntesisBindingConstants {

// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_INTESISHOME = new ThingTypeUID(BINDING_ID, "intesisHome");
public static final ThingTypeUID THING_TYPE_INTESISBOX = new ThingTypeUID(BINDING_ID, "intesisBox");

// List of all Channel ids
public static final String CHANNEL_TYPE_POWER = "power";
Expand All @@ -41,4 +42,6 @@ public class IntesisBindingConstants {
public static final String CHANNEL_TYPE_TARGETTEMP = "targetTemperature";
public static final String CHANNEL_TYPE_AMBIENTTEMP = "ambientTemperature";
public static final String CHANNEL_TYPE_OUTDOORTEMP = "outdoorTemperature";
public static final String CHANNEL_TYPE_ERRORCODE = "errorCode";
public static final String CHANNEL_TYPE_ERRORSTATUS = "errorStatus";
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@
*/
package org.openhab.binding.intesis.internal;

import static org.openhab.binding.intesis.internal.IntesisBindingConstants.THING_TYPE_INTESISHOME;
import static org.openhab.binding.intesis.internal.IntesisBindingConstants.*;

import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.intesis.internal.handler.IntesisBoxHandler;
import org.openhab.binding.intesis.internal.handler.IntesisHomeHandler;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.thing.Thing;
Expand Down Expand Up @@ -48,7 +51,8 @@ public class IntesisHandlerFactory extends BaseThingHandlerFactory {
private final HttpClient httpClient;
private final IntesisDynamicStateDescriptionProvider intesisStateDescriptionProvider;

private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_INTESISHOME);
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_INTESISHOME, THING_TYPE_INTESISBOX).collect(Collectors.toSet()));

@Activate
public IntesisHandlerFactory(@Reference HttpClientFactory httpClientFactory, ComponentContext componentContext,
Expand All @@ -73,6 +77,11 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return new IntesisHomeHandler(thing, httpClient, intesisStateDescriptionProvider);
}

if (THING_TYPE_INTESISBOX.equals(thingTypeUID)) {
logger.debug("Creating a IntesisBoxHandler for thing '{}'", thing.getUID());
hmerk marked this conversation as resolved.
Show resolved Hide resolved
return new IntesisBoxHandler(thing, intesisStateDescriptionProvider);
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* 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.intesis.internal.api;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.thing.ThingStatus;

/**
* The {@link IntesisBoxChangeListener} is in interface for a IntesisBox changed consumer
*
* @author Hans-Jörg Merk - Initial contribution
*/
@NonNullByDefault
public interface IntesisBoxChangeListener {
/**
* This method will be called in case a message was received.
*
*/
void messageReceived(String messageLine);

/**
* This method will be called in case the connection status has changed.
*
*/
void connectionStatusChanged(ThingStatus status, @Nullable String message);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* 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.intesis.internal.api;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

/**
* @author Cody Cutrer - Initial contribution
*/
@NonNullByDefault
public class IntesisBoxMessage {
public static final String ID = "ID";
public static final String INFO = "INFO";
public static final String SET = "SET";
public static final String CHN = "CHN";
public static final String GET = "GET";
public static final String LOGIN = "LOGIN";
public static final String LOGOUT = "LOGOUT";
public static final String CFG = "CFG";
public static final String LIMITS = "LIMITS";
public static final String DISCOVER = "DISCOVER";

private static final Pattern REGEX = Pattern.compile("^([^,]+)(?:,(\\d+))?:([^,]+),([A-Z0-9.,\\[\\]]+)$");

@SuppressWarnings("unused")
private final String acNum;
private final String command;
private final String function;
private final String value;

private IntesisBoxMessage(String command, String acNum, String function, String value) {
this.command = command;
this.acNum = acNum;
this.function = function;
this.value = value;
}

public String getCommand() {
return command;
}

public String getFunction() {
return function;
}

public String getValue() {
return value;
}

public List<String> getLimitsValue() {
return Arrays.asList(value.substring(1, value.length() - 1).split(","));
}

public static @Nullable IntesisBoxMessage parse(String message) {
Matcher m = REGEX.matcher(message);
if (!m.find()) {
return null;
}

return new IntesisBoxMessage(m.group(1), m.group(2), m.group(3), m.group(4));
}
}
Loading