mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[intesis] - added IntesisBox support (#8694)
* Intesis Binding - added IntesisBox support Signed-off-by: Hans-Jörg Merk <github@hmerk.de>
This commit is contained in:
parent
8b8b79cf04
commit
91fbe746e9
@ -1,7 +1,6 @@
|
||||
# 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.
|
||||
|
||||
|
||||
|
||||
@ -9,9 +8,10 @@ It does actually not support [IntesisBox](http://www.intesisbox.com/) devices bu
|
||||
|
||||
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
|
||||
|
||||
@ -19,35 +19,40 @@ 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 |
|
||||
| wifiSignal | Number | (Readonly) WiFi signal strength (IntesisBox only) | 4=excellent, 3=good, 2=not string, 1=unreliable, 0=none |
|
||||
|
||||
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
|
||||
|
||||
@ -55,8 +60,9 @@ The binding can be fully setup from the UI but if you decide to use files here i
|
||||
|
||||
**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**
|
||||
@ -89,4 +95,3 @@ sitemap intesishome label="My AC control" {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -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";
|
||||
@ -41,4 +42,7 @@ 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";
|
||||
public static final String CHANNEL_TYPE_RSSI = "wifiSignal";
|
||||
}
|
||||
|
@ -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;
|
||||
@ -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,
|
||||
@ -69,10 +73,13 @@ public class IntesisHandlerFactory extends BaseThingHandlerFactory {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_INTESISHOME.equals(thingTypeUID)) {
|
||||
logger.debug("Creating a IntesisHomeHandler for thing '{}'", thing.getUID());
|
||||
return new IntesisHomeHandler(thing, httpClient, intesisStateDescriptionProvider);
|
||||
}
|
||||
|
||||
if (THING_TYPE_INTESISBOX.equals(thingTypeUID)) {
|
||||
return new IntesisBoxHandler(thing, intesisStateDescriptionProvider);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -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.intesis.internal.api;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.intesis.internal.handler.IntesisBoxHandler;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Class handling the Socket connections.
|
||||
*
|
||||
* @author Cody Cutrer - Initial contribution
|
||||
* @author Hans-Jörg Merk - Moved Socket to it's own class
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class IntesisBoxSocketApi {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(IntesisBoxSocketApi.class);
|
||||
|
||||
private final String ipAddress;
|
||||
private final int port;
|
||||
private final String readerThreadName;
|
||||
|
||||
private @Nullable IntesisSocket tcpSocket = null;
|
||||
private @Nullable OutputStreamWriter tcpOutput = null;
|
||||
private @Nullable BufferedReader tcpInput = null;
|
||||
|
||||
private @Nullable IntesisBoxChangeListener changeListener;
|
||||
|
||||
private boolean connected = false;
|
||||
|
||||
public IntesisBoxSocketApi(final String ipAddress, final int port, final String readerThreadName) {
|
||||
this.ipAddress = ipAddress;
|
||||
this.port = port;
|
||||
this.readerThreadName = readerThreadName;
|
||||
}
|
||||
|
||||
private class IntesisSocket {
|
||||
final Socket socket;
|
||||
|
||||
public IntesisSocket() throws UnknownHostException, IOException {
|
||||
socket = new Socket();
|
||||
SocketAddress tcpSocketAddress = new InetSocketAddress(ipAddress, port);
|
||||
socket.connect(tcpSocketAddress);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void openConnection() throws IOException {
|
||||
closeConnection();
|
||||
|
||||
IntesisBoxChangeListener listener = this.changeListener;
|
||||
IntesisSocket localSocket = tcpSocket = new IntesisSocket();
|
||||
tcpOutput = new OutputStreamWriter(localSocket.socket.getOutputStream(), StandardCharsets.US_ASCII);
|
||||
tcpInput = new BufferedReader(
|
||||
new InputStreamReader(localSocket.socket.getInputStream(), StandardCharsets.US_ASCII));
|
||||
|
||||
Thread tcpListener = new Thread(new TCPListener());
|
||||
tcpListener.setName(readerThreadName);
|
||||
tcpListener.setDaemon(true);
|
||||
tcpListener.start();
|
||||
|
||||
setConnected(true);
|
||||
if (listener != null) {
|
||||
listener.connectionStatusChanged(ThingStatus.ONLINE, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeConnection() {
|
||||
try {
|
||||
IntesisSocket localSocket = tcpSocket;
|
||||
OutputStreamWriter localOutput = tcpOutput;
|
||||
BufferedReader localInput = tcpInput;
|
||||
|
||||
if (localSocket != null) {
|
||||
localSocket.close();
|
||||
localSocket = null;
|
||||
}
|
||||
if (localInput != null) {
|
||||
localInput.close();
|
||||
localInput = null;
|
||||
}
|
||||
if (localOutput != null) {
|
||||
localOutput.close();
|
||||
localOutput = null;
|
||||
}
|
||||
setConnected(false);
|
||||
} catch (IOException ioException) {
|
||||
logger.debug("closeConnection(): Unable to close connection - {}", ioException.getMessage());
|
||||
} catch (Exception exception) {
|
||||
logger.debug("closeConnection(): Error closing connection - {}", exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private class TCPListener implements Runnable {
|
||||
|
||||
/**
|
||||
* Run method. Runs the MessageListener thread
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
while (isConnected()) {
|
||||
String message = read();
|
||||
readMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addIntesisBoxChangeListener(IntesisBoxChangeListener listener) {
|
||||
if (this.changeListener == null) {
|
||||
this.changeListener = listener;
|
||||
}
|
||||
}
|
||||
|
||||
private void write(String data) {
|
||||
IntesisBoxChangeListener listener = this.changeListener;
|
||||
try {
|
||||
OutputStreamWriter localOutput = tcpOutput;
|
||||
|
||||
if (localOutput != null) {
|
||||
localOutput.write(data);
|
||||
localOutput.flush();
|
||||
}
|
||||
} catch (IOException ioException) {
|
||||
setConnected(false);
|
||||
if (listener != null) {
|
||||
listener.connectionStatusChanged(ThingStatus.OFFLINE, ioException.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String read() {
|
||||
String message = "";
|
||||
try {
|
||||
BufferedReader localInput = tcpInput;
|
||||
if (localInput != null) {
|
||||
message = localInput.readLine();
|
||||
}
|
||||
} catch (IOException ioException) {
|
||||
setConnected(false);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public void readMessage(String message) {
|
||||
IntesisBoxChangeListener listener = this.changeListener;
|
||||
|
||||
if (listener != null && !message.isEmpty()) {
|
||||
listener.messageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendAlive() {
|
||||
write("GET,1:*\r\n");
|
||||
}
|
||||
|
||||
public void sendId() {
|
||||
write("ID\r\n");
|
||||
}
|
||||
|
||||
public void sendLimitsQuery() {
|
||||
write("LIMITS:*\r\n");
|
||||
}
|
||||
|
||||
public void sendCommand(String function, String value) {
|
||||
String data = String.format("SET,1:%s,%s\r\n", function, value);
|
||||
write(data);
|
||||
}
|
||||
|
||||
public void sendQuery(String function) {
|
||||
String data = String.format("GET,1:%s\r\n", function);
|
||||
write(data);
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return this.connected;
|
||||
}
|
||||
|
||||
public void setConnected(boolean connected) {
|
||||
this.connected = connected;
|
||||
}
|
||||
|
||||
public void removeIntesisBoxChangeListener(IntesisBoxHandler intesisBoxHandler) {
|
||||
if (this.changeListener != null) {
|
||||
this.changeListener = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.openhab.binding.intesis.internal.IntesisConfiguration;
|
||||
import org.openhab.binding.intesis.internal.config.IntesisHomeConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -40,7 +40,7 @@ public class IntesisHomeHttpApi {
|
||||
private final Logger logger = LoggerFactory.getLogger(IntesisHomeHttpApi.class);
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public IntesisHomeHttpApi(IntesisConfiguration config, HttpClient httpClient) {
|
||||
public IntesisHomeHttpApi(IntesisHomeConfiguration config, HttpClient httpClient) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The {@link DataPointChangedEvent} is an event container for data point changes
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MessageReceivedEvent {
|
||||
protected String message;
|
||||
|
||||
public MessageReceivedEvent(Object source, String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data-point of the event.
|
||||
*
|
||||
*/
|
||||
@Nullable
|
||||
public String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link IntesisBoxConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class IntesisBoxConfiguration {
|
||||
public String ipAddress = "";
|
||||
public int port;
|
||||
}
|
@ -10,17 +10,17 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.intesis.internal;
|
||||
package org.openhab.binding.intesis.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link IntesisConfiguration} class contains fields mapping thing configuration parameters.
|
||||
* The {@link IntesisHomeConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class IntesisConfiguration {
|
||||
public class IntesisHomeConfiguration {
|
||||
public String ipAddress = "";
|
||||
public String password = "";
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.intesis.internal;
|
||||
package org.openhab.binding.intesis.internal.enums;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
@ -0,0 +1,394 @@
|
||||
/**
|
||||
* 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.handler;
|
||||
|
||||
import static org.openhab.binding.intesis.internal.IntesisBindingConstants.*;
|
||||
import static org.openhab.binding.intesis.internal.api.IntesisBoxMessage.*;
|
||||
import static org.openhab.core.thing.Thing.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.intesis.internal.IntesisDynamicStateDescriptionProvider;
|
||||
import org.openhab.binding.intesis.internal.api.IntesisBoxChangeListener;
|
||||
import org.openhab.binding.intesis.internal.api.IntesisBoxMessage;
|
||||
import org.openhab.binding.intesis.internal.api.IntesisBoxSocketApi;
|
||||
import org.openhab.binding.intesis.internal.config.IntesisBoxConfiguration;
|
||||
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.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.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.type.ChannelKind;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.StateOption;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link IntesisBoxHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cody Cutrer - Initial contribution
|
||||
* @author Rocky Amatulli - additions to include id message handling, dynamic channel options based on limits.
|
||||
* @author Hans-Jörg Merk - refactored for openHAB 3.0 compatibility
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class IntesisBoxHandler extends BaseThingHandler implements IntesisBoxChangeListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(IntesisBoxHandler.class);
|
||||
private @Nullable IntesisBoxSocketApi intesisBoxSocketApi;
|
||||
|
||||
private final Map<String, String> properties = new HashMap<>();
|
||||
private final Map<String, List<String>> limits = new HashMap<>();
|
||||
|
||||
private final IntesisDynamicStateDescriptionProvider intesisStateDescriptionProvider;
|
||||
|
||||
private IntesisBoxConfiguration config = new IntesisBoxConfiguration();
|
||||
|
||||
private double minTemp = 0.0, maxTemp = 0.0;
|
||||
|
||||
private boolean hasProperties = false;
|
||||
|
||||
private @Nullable ScheduledFuture<?> pollingTask;
|
||||
|
||||
public IntesisBoxHandler(Thing thing, IntesisDynamicStateDescriptionProvider intesisStateDescriptionProvider) {
|
||||
super(thing);
|
||||
this.intesisStateDescriptionProvider = intesisStateDescriptionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
config = getConfigAs(IntesisBoxConfiguration.class);
|
||||
|
||||
if (!config.ipAddress.isEmpty()) {
|
||||
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
scheduler.submit(() -> {
|
||||
|
||||
String readerThreadName = "OH-binding-" + getThing().getUID().getAsString();
|
||||
|
||||
IntesisBoxSocketApi intesisLocalApi = intesisBoxSocketApi = new IntesisBoxSocketApi(config.ipAddress,
|
||||
config.port, readerThreadName);
|
||||
intesisLocalApi.addIntesisBoxChangeListener(this);
|
||||
try {
|
||||
intesisLocalApi.openConnection();
|
||||
intesisLocalApi.sendId();
|
||||
intesisLocalApi.sendLimitsQuery();
|
||||
intesisLocalApi.sendAlive();
|
||||
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
return;
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
});
|
||||
pollingTask = scheduler.scheduleWithFixedDelay(this::polling, 3, 45, TimeUnit.SECONDS);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No IP address specified)");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
final ScheduledFuture<?> pollingTask = this.pollingTask;
|
||||
|
||||
IntesisBoxSocketApi api = this.intesisBoxSocketApi;
|
||||
|
||||
if (pollingTask != null) {
|
||||
pollingTask.cancel(true);
|
||||
this.pollingTask = null;
|
||||
}
|
||||
if (api != null) {
|
||||
api.closeConnection();
|
||||
api.removeIntesisBoxChangeListener(this);
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private synchronized void polling() {
|
||||
IntesisBoxSocketApi api = this.intesisBoxSocketApi;
|
||||
if (api != null) {
|
||||
if (!api.isConnected()) {
|
||||
try {
|
||||
api.openConnection();
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
api.sendAlive();
|
||||
api.sendId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
IntesisBoxSocketApi api = this.intesisBoxSocketApi;
|
||||
if (api != null) {
|
||||
if (!api.isConnected()) {
|
||||
logger.trace("Sending command failed, not connected");
|
||||
return;
|
||||
}
|
||||
if (command instanceof RefreshType) {
|
||||
logger.trace("Refresh channel {}", channelUID.getId());
|
||||
api.sendQuery(channelUID.getId());
|
||||
return;
|
||||
}
|
||||
}
|
||||
String value = "";
|
||||
String function = "";
|
||||
switch (channelUID.getId()) {
|
||||
case CHANNEL_TYPE_POWER:
|
||||
if (command instanceof OnOffType) {
|
||||
function = "ONOFF";
|
||||
value = command == OnOffType.ON ? "ON" : "OFF";
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_TARGETTEMP:
|
||||
if (command instanceof QuantityType) {
|
||||
QuantityType<?> celsiusTemperature = (QuantityType<?>) command;
|
||||
celsiusTemperature = celsiusTemperature.toUnit(SIUnits.CELSIUS);
|
||||
if (celsiusTemperature != null) {
|
||||
double doubleValue = celsiusTemperature.doubleValue();
|
||||
logger.trace("targetTemp double value = {}", doubleValue);
|
||||
doubleValue = Math.max(minTemp, Math.min(maxTemp, doubleValue));
|
||||
value = String.format("%.0f", doubleValue * 10);
|
||||
function = "SETPTEMP";
|
||||
logger.trace("targetTemp raw string = {}", value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_TYPE_MODE:
|
||||
function = "MODE";
|
||||
value = command.toString();
|
||||
break;
|
||||
case CHANNEL_TYPE_FANSPEED:
|
||||
function = "FANSP";
|
||||
value = command.toString();
|
||||
break;
|
||||
case CHANNEL_TYPE_VANESUD:
|
||||
function = "VANEUD";
|
||||
value = command.toString();
|
||||
break;
|
||||
case CHANNEL_TYPE_VANESLR:
|
||||
function = "VANELR";
|
||||
value = command.toString();
|
||||
break;
|
||||
}
|
||||
if (!value.isEmpty() || function.isEmpty()) {
|
||||
if (api != null) {
|
||||
logger.trace("Sending command {} to function {}", value, function);
|
||||
api.sendCommand(function, value);
|
||||
} else {
|
||||
logger.warn("Sending command failed, could not get API");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void populateProperties(String[] value) {
|
||||
properties.put(PROPERTY_VENDOR, "Intesis");
|
||||
properties.put(PROPERTY_MODEL_ID, value[0]);
|
||||
properties.put(PROPERTY_MAC_ADDRESS, value[1]);
|
||||
properties.put("ipAddress", value[2]);
|
||||
properties.put("protocol", value[3]);
|
||||
properties.put(PROPERTY_FIRMWARE_VERSION, value[4]);
|
||||
properties.put("hostname", value[6]);
|
||||
updateProperties(properties);
|
||||
hasProperties = true;
|
||||
}
|
||||
|
||||
private void receivedUpdate(String function, String receivedValue) {
|
||||
String value = receivedValue;
|
||||
logger.trace("receivedUpdate(): {} {}", function, value);
|
||||
switch (function) {
|
||||
case "ONOFF":
|
||||
updateState(CHANNEL_TYPE_POWER, OnOffType.from(value));
|
||||
break;
|
||||
|
||||
case "SETPTEMP":
|
||||
if (value.equals("32768")) {
|
||||
value = "0";
|
||||
}
|
||||
updateState(CHANNEL_TYPE_TARGETTEMP,
|
||||
new QuantityType<Temperature>(Double.valueOf(value) / 10.0d, SIUnits.CELSIUS));
|
||||
break;
|
||||
case "AMBTEMP":
|
||||
if (Double.valueOf(value).isNaN()) {
|
||||
value = "0";
|
||||
}
|
||||
updateState(CHANNEL_TYPE_AMBIENTTEMP,
|
||||
new QuantityType<Temperature>(Double.valueOf(value) / 10.0d, SIUnits.CELSIUS));
|
||||
break;
|
||||
case "MODE":
|
||||
updateState(CHANNEL_TYPE_MODE, new StringType(value));
|
||||
break;
|
||||
case "FANSP":
|
||||
updateState(CHANNEL_TYPE_FANSPEED, new StringType(value));
|
||||
break;
|
||||
case "VANEUD":
|
||||
updateState(CHANNEL_TYPE_VANESUD, new StringType(value));
|
||||
break;
|
||||
case "VANELR":
|
||||
updateState(CHANNEL_TYPE_VANESLR, new StringType(value));
|
||||
break;
|
||||
case "ERRCODE":
|
||||
properties.put("errorCode", value);
|
||||
updateProperties(properties);
|
||||
break;
|
||||
case "ERRSTATUS":
|
||||
properties.put("errorStatus", value);
|
||||
updateProperties(properties);
|
||||
if ("ERR".equals(value)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"device reported an error");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMessage(String data) {
|
||||
logger.debug("handleMessage(): Message received - {}", data);
|
||||
if (data.equals("ACK") || data.equals("")) {
|
||||
return;
|
||||
}
|
||||
if (data.startsWith(ID + ':')) {
|
||||
String[] value = data.substring(3).split(",");
|
||||
if (!hasProperties) {
|
||||
populateProperties(value);
|
||||
}
|
||||
DecimalType signalStrength = mapSignalStrength(Integer.parseInt(value[5]));
|
||||
updateState(CHANNEL_TYPE_RSSI, signalStrength);
|
||||
return;
|
||||
}
|
||||
IntesisBoxMessage message = IntesisBoxMessage.parse(data);
|
||||
if (message != null) {
|
||||
switch (message.getCommand()) {
|
||||
case LIMITS:
|
||||
logger.debug("handleMessage(): Limits received - {}", data);
|
||||
String function = message.getFunction();
|
||||
if (function.equals("SETPTEMP")) {
|
||||
List<Double> limits = message.getLimitsValue().stream().map(l -> Double.valueOf(l) / 10.0d)
|
||||
.collect(Collectors.toList());
|
||||
if (limits.size() == 2) {
|
||||
minTemp = limits.get(0);
|
||||
maxTemp = limits.get(1);
|
||||
}
|
||||
logger.trace("Property target temperatures {} added", message.getValue());
|
||||
properties.put("targetTemperature limits", "[" + minTemp + "," + maxTemp + "]");
|
||||
addChannel(CHANNEL_TYPE_TARGETTEMP, "Number:Temperature");
|
||||
} else {
|
||||
switch (function) {
|
||||
case "MODE":
|
||||
properties.put("supported modes", message.getValue());
|
||||
limits.put(CHANNEL_TYPE_MODE, message.getLimitsValue());
|
||||
addChannel(CHANNEL_TYPE_MODE, "String");
|
||||
break;
|
||||
case "FANSP":
|
||||
properties.put("supported fan levels", message.getValue());
|
||||
limits.put(CHANNEL_TYPE_FANSPEED, message.getLimitsValue());
|
||||
addChannel(CHANNEL_TYPE_FANSPEED, "String");
|
||||
break;
|
||||
case "VANEUD":
|
||||
properties.put("supported vane up/down modes", message.getValue());
|
||||
limits.put(CHANNEL_TYPE_VANESUD, message.getLimitsValue());
|
||||
addChannel(CHANNEL_TYPE_VANESUD, "String");
|
||||
break;
|
||||
case "VANELR":
|
||||
properties.put("supported vane left/right modes", message.getValue());
|
||||
limits.put(CHANNEL_TYPE_VANESLR, message.getLimitsValue());
|
||||
addChannel(CHANNEL_TYPE_VANESLR, "String");
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateProperties(properties);
|
||||
break;
|
||||
case CHN:
|
||||
receivedUpdate(message.getFunction(), message.getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addChannel(String channelId, String itemType) {
|
||||
if (thing.getChannel(channelId) == null) {
|
||||
logger.trace("Channel '{}' for UID to be added", channelId);
|
||||
ThingBuilder thingBuilder = editThing();
|
||||
final ChannelTypeUID channelTypeUID = new ChannelTypeUID(BINDING_ID, channelId);
|
||||
Channel channel = ChannelBuilder.create(new ChannelUID(getThing().getUID(), channelId), itemType)
|
||||
.withType(channelTypeUID).withKind(ChannelKind.STATE).build();
|
||||
thingBuilder.withChannel(channel);
|
||||
updateThing(thingBuilder.build());
|
||||
|
||||
if (limits.containsKey(channelId)) {
|
||||
List<StateOption> options = new ArrayList<>();
|
||||
for (String mode : limits.get(channelId)) {
|
||||
options.add(new StateOption(mode,
|
||||
mode.substring(0, 1).toUpperCase() + mode.substring(1).toLowerCase()));
|
||||
}
|
||||
intesisStateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), channelId),
|
||||
options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(String messageLine) {
|
||||
logger.trace("messageReceived() : {}", messageLine);
|
||||
handleMessage(messageLine);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionStatusChanged(ThingStatus status, @Nullable String message) {
|
||||
if (message != null) {
|
||||
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);
|
||||
}
|
||||
this.updateStatus(status);
|
||||
}
|
||||
|
||||
public static DecimalType mapSignalStrength(int dbm) {
|
||||
int strength = -1;
|
||||
if (dbm > -60) {
|
||||
strength = 4;
|
||||
} else if (dbm > -70) {
|
||||
strength = 3;
|
||||
} else if (dbm > -80) {
|
||||
strength = 2;
|
||||
} else if (dbm > -90) {
|
||||
strength = 1;
|
||||
} else {
|
||||
strength = 0;
|
||||
}
|
||||
return new DecimalType(strength);
|
||||
}
|
||||
}
|
@ -29,10 +29,10 @@ import java.util.stream.Collectors;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.intesis.internal.IntesisConfiguration;
|
||||
import org.openhab.binding.intesis.internal.IntesisDynamicStateDescriptionProvider;
|
||||
import org.openhab.binding.intesis.internal.IntesisHomeModeEnum;
|
||||
import org.openhab.binding.intesis.internal.api.IntesisHomeHttpApi;
|
||||
import org.openhab.binding.intesis.internal.config.IntesisHomeConfiguration;
|
||||
import org.openhab.binding.intesis.internal.enums.IntesisHomeModeEnum;
|
||||
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Data;
|
||||
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Datapoints;
|
||||
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Descr;
|
||||
@ -83,7 +83,7 @@ public class IntesisHomeHandler extends BaseThingHandler {
|
||||
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
private IntesisConfiguration config = new IntesisConfiguration();
|
||||
private IntesisHomeConfiguration config = new IntesisHomeConfiguration();
|
||||
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
|
||||
@ -97,7 +97,7 @@ public class IntesisHomeHandler extends BaseThingHandler {
|
||||
@Override
|
||||
public void initialize() {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
config = getConfigAs(IntesisConfiguration.class);
|
||||
config = getConfigAs(IntesisHomeConfiguration.class);
|
||||
if (config.ipAddress.isEmpty() && config.password.isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "IP-Address and password not set");
|
||||
return;
|
||||
@ -336,7 +336,7 @@ public class IntesisHomeHandler extends BaseThingHandler {
|
||||
break;
|
||||
}
|
||||
}
|
||||
properties.put("Supported modes", opModes.toString());
|
||||
properties.put("supported modes", opModes.toString());
|
||||
channelId = CHANNEL_TYPE_MODE;
|
||||
addChannel(channelId, itemType, opModes);
|
||||
break;
|
||||
@ -349,7 +349,7 @@ public class IntesisHomeHandler extends BaseThingHandler {
|
||||
fanLevels.add(fanString);
|
||||
}
|
||||
}
|
||||
properties.put("Supported fan levels", fanLevels.toString());
|
||||
properties.put("supported fan levels", fanLevels.toString());
|
||||
channelId = CHANNEL_TYPE_FANSPEED;
|
||||
addChannel(channelId, itemType, fanLevels);
|
||||
break;
|
||||
@ -372,12 +372,12 @@ public class IntesisHomeHandler extends BaseThingHandler {
|
||||
switch (datapoint.uid) {
|
||||
case 5:
|
||||
channelId = CHANNEL_TYPE_VANESUD;
|
||||
properties.put("Supported vane up/down modes", swingModes.toString());
|
||||
properties.put("supported vane up/down modes", swingModes.toString());
|
||||
addChannel(channelId, itemType, swingModes);
|
||||
break;
|
||||
case 6:
|
||||
channelId = CHANNEL_TYPE_VANESLR;
|
||||
properties.put("Supported vane left/right modes", swingModes.toString());
|
||||
properties.put("supported vane left/right modes", swingModes.toString());
|
||||
addChannel(channelId, itemType, swingModes);
|
||||
break;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ channel-type.intesis.ambientTemperature.label = Ambient Temperature
|
||||
channel-type.intesis.ambientTemperature.description = Shows actual room temperature.
|
||||
channel-type.intesis.outdoorTemperature.label = Outdoor Temperature
|
||||
channel-type.intesis.outdoorTemperature.description = Shows actual outdoor temperature.
|
||||
channel-type.intesis.fanSpeed.label = Wind Speed
|
||||
channel-type.intesis.fanSpeed.label = Fan Speed
|
||||
channel-type.intesis.fanSpeed.description = Sets the fan speed on the Air conditioner.
|
||||
channel-type.intesis.fanSpeed.state.option.auto = Auto
|
||||
channel-type.intesis.vanesUpDown.label = Vertical Swing Mode
|
||||
@ -40,3 +40,7 @@ channel-type.intesis.vanes.option.auto = AUTO
|
||||
channel-type.intesis.vanes.option.swing = Swing
|
||||
channel-type.intesis.vanes.option.swirl = Swirl
|
||||
channel-type.intesis.vanes.option.wide = Wide
|
||||
channel-type.intesis.errorCode.label = Error Code
|
||||
channel-type.intesis.errorCode.description = Shows the Air Conditioners error code if an error was found.
|
||||
channel-type.intesis.errorStatus.label = Error Status
|
||||
channel-type.intesis.errorStatus.description = Indicates if the Air Conditioner has encountered an error.
|
||||
|
@ -40,3 +40,8 @@ channel-type.intesis.vanes.option.auto = Auto
|
||||
channel-type.intesis.vanes.option.swing = Schwingen
|
||||
channel-type.intesis.vanes.option.swirl = Pulsieren
|
||||
channel-type.intesis.vanes.option.wide = Breit
|
||||
channel-type.intesis.errorCode.label = Fehlercode
|
||||
channel-type.intesis.errorCode.description = Zeigt im Fehlerzustand den Fehlercode an.
|
||||
channel-type.intesis.errorStatus.label = Fehlerstatus
|
||||
channel-type.intesis.errorStatus.description = Zeigt an, ob sich der Air Conditioner im Zustand "Fehler" befindet.
|
||||
|
||||
|
@ -23,4 +23,48 @@
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="intesisBox">
|
||||
<label>IntesisBox Adapter</label>
|
||||
<description>Represents a single IntesisBox adapter on the network, connected to an A/C unit.</description>
|
||||
<channels>
|
||||
<channel id="power" typeId="system.power"/>
|
||||
<channel id="wifiSignal" typeId="system.signal-strength"/>
|
||||
<channel id="ambientTemperature" typeId="ambientTemperature"/>
|
||||
<channel id="errorCode" typeId="errorCode"/>
|
||||
<channel id="errorStatus" typeId="errorStatus"/>
|
||||
</channels>
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>@text/thing-type.config.intesis.ipAddress.label</label>
|
||||
<description>@text/thing-type.config.intesis.ipAddress.description</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" required="true">
|
||||
<label>Port</label>
|
||||
<description>The TCP port to the IntesisBox.</description>
|
||||
<default>3310</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="ambientTemperature">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>@text/channel-type.intesis.ambientTemperature.label</label>
|
||||
<description>@text/channel-type.intesis.ambientTemperature.description</description>
|
||||
<state pattern="%d %unit%" readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="errorCode">
|
||||
<item-type>String</item-type>
|
||||
<label>@text/channel-type.intesis.errorCode.label</label>
|
||||
<description>@text/channel-type.intesis.errorCode.description</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="errorStatus">
|
||||
<item-type>String</item-type>
|
||||
<label>@text/channel-type.intesis.errorStatus.label</label>
|
||||
<description>@text/channel-type.intesis.errorStatus.description</description>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
Loading…
Reference in New Issue
Block a user