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,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.intesis-${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-intesis" description="Intesis Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.intesis/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,44 @@
/**
* 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;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link IntesisBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Hans-Jörg Merk - Initial contribution
*/
@NonNullByDefault
public class IntesisBindingConstants {
public static final String BINDING_ID = "intesis";
public static final int INTESIS_HTTP_API_TIMEOUT_MS = 5000;
public static final int INTESIS_REFRESH_INTERVAL_SEC = 30;
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_INTESISHOME = new ThingTypeUID(BINDING_ID, "intesisHome");
// List of all Channel ids
public static final String CHANNEL_TYPE_POWER = "power";
public static final String CHANNEL_TYPE_MODE = "mode";
public static final String CHANNEL_TYPE_FANSPEED = "fanSpeed";
public static final String CHANNEL_TYPE_VANESUD = "vanesUpDown";
public static final String CHANNEL_TYPE_VANESLR = "vanesLeftRight";
public static final String CHANNEL_TYPE_TARGETTEMP = "targetTemperature";
public static final String CHANNEL_TYPE_AMBIENTTEMP = "ambientTemperature";
public static final String CHANNEL_TYPE_OUTDOORTEMP = "outdoorTemperature";
}

View File

@@ -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;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link IntesisConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Hans-Jörg Merk - Initial contribution
*/
@NonNullByDefault
public class IntesisConfiguration {
public String ipAddress = "";
public String password = "";
}

View File

@@ -0,0 +1,28 @@
/**
* 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;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider;
import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
import org.osgi.service.component.annotations.Component;
/**
*
* @author Hans-Jörg Merk - Initial contribution
*/
@Component(service = { DynamicStateDescriptionProvider.class, IntesisDynamicStateDescriptionProvider.class })
@NonNullByDefault
public class IntesisDynamicStateDescriptionProvider extends BaseDynamicStateDescriptionProvider {
}

View File

@@ -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;
import static org.openhab.binding.intesis.internal.IntesisBindingConstants.THING_TYPE_INTESISHOME;
import java.util.Collections;
import java.util.Set;
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.IntesisHomeHandler;
import org.openhab.core.io.net.http.HttpClientFactory;
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.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link IntesisHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Hans-Jörg Merk - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.intesis", service = ThingHandlerFactory.class)
public class IntesisHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(IntesisHandlerFactory.class);
private final HttpClient httpClient;
private final IntesisDynamicStateDescriptionProvider intesisStateDescriptionProvider;
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_INTESISHOME);
@Activate
public IntesisHandlerFactory(@Reference HttpClientFactory httpClientFactory, ComponentContext componentContext,
final @Reference IntesisDynamicStateDescriptionProvider dynamicStateDescriptionProvider) {
super.activate(componentContext);
this.httpClient = httpClientFactory.getCommonHttpClient();
this.intesisStateDescriptionProvider = dynamicStateDescriptionProvider;
}
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
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);
}
return null;
}
}

View File

@@ -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;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link IntesisModeEnum) contains informations for translating device modes into internally used numbers.
*
* @author Hans-Jörg Merk - Initial contribution
*/
@NonNullByDefault
public enum IntesisHomeModeEnum {
AUTO(0),
HEAT(1),
DRY(2),
FAN(3),
COOL(4);
private final int mode;
private IntesisHomeModeEnum(int mode) {
this.mode = mode;
}
public int getMode() {
return mode;
}
}

View File

@@ -0,0 +1,76 @@
/**
* 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.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link IntesisHomeHttpApi} wraps the IntesisHome REST API and provides various low level function to access the
* device api (not cloud api).
*
* @author Hans-Jörg Merk - Initial contribution
*/
@NonNullByDefault
public class IntesisHomeHttpApi {
public static final String CONTENT_TYPE_JSON = "application/json; charset=UTF-8";
private final Logger logger = LoggerFactory.getLogger(IntesisHomeHttpApi.class);
private final HttpClient httpClient;
public IntesisHomeHttpApi(IntesisConfiguration config, HttpClient httpClient) {
this.httpClient = httpClient;
}
/**
* Used to post a request to the device
*
* @param ipAddress of the device
* @param content string
* @return JSON string as response
*/
@Nullable
public String postRequest(String ipAddress, String contentString) {
String url = "http://" + ipAddress + "/api.cgi";
try {
Request request = httpClient.POST(url);
request.header(HttpHeader.CONTENT_TYPE, "application/json");
request.content(new StringContentProvider(contentString), "application/json");
ContentResponse contentResponse = request.timeout(5, TimeUnit.SECONDS).send();
String response = contentResponse.getContentAsString().replace("\t", "").replace("\r\n", "").trim();
if (response != null && !response.isEmpty()) {
return response;
} else {
return null;
}
} catch (TimeoutException | InterruptedException | ExecutionException e) {
logger.debug("Could not make HTTP Post request");
}
return null;
}
}

View File

@@ -0,0 +1,123 @@
/**
* 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.gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
/**
* {@link IntesisHomeJSonDTO} is used for the JSon/GSon mapping
*
* @author Hans-Jörg Merk - Initial contribution
*/
public class IntesisHomeJSonDTO {
public static class Response {
public boolean success;
public JsonElement data;
}
public static class Data {
public JsonElement id;
public JsonElement info;
public JsonElement userinfo;
public JsonElement config;
public JsonElement dp;
public JsonElement dpval;
}
public static class Id {
public String sessionID; // Session ID
}
// Device Information used for thing properties
public static class Info {
public String wlanSTAMAC; // Device Client MAC Address
public String wlanAPMAC; // Device Access Point MAC Address
public String fwVersion; // Device Firmware Version
public String wlanFwVersion; // Wireless Firmware Version
public String acStatus; // Air Conditioner Communication Status
public String wlanLNK; // Connection Status with Wireless Network
public String ssid; // Wireless Network SSID
public String rssi; // Wireless Signal Strength
public String tcpServerLNK; // Cloud Server Connection (Not used for communication here)
public String localdatetime; // Local Date Time
public String powerStatus;
public String lastconfigdatetime; // Last Configuration Date Time
public String deviceModel; // Device Model
public String sn; // Serial Number
public String lastError;
}
public static class Userinfo {
public String username;
public JsonElement servicelist;
}
// List of available services
public static class Servicelist {
public String setconfig;
public String getconfig;
public String getcurrentconfig;
public String getinfo;
public String login;
public String logout;
public String passchange;
public String getavailabledatapoints;
public String setdatapointvalue;
public String getdatapointvalue;
public String getavailableservices;
public String reboot;
public String setdefaults;
public String getdefaultconfig;
}
public static class Config {
public String deviceModel; // Device Model
public String ip; // Device IP Address
public String netmask; // Device IP Address
public String dfltgw; // Default gateway
public boolean dhcp; // DHCP enabled
public String ssid; // WLAN Access Point
public int security; // Security Type
public int regdomain;
public int lastconfigdatetime;
}
public static class Dp {
public JsonArray datapoints; // dataPoints
}
// Array of UIDs with corresponding description for dynamic channel creation
public static class Datapoints {
public int uid; // dataPoint
public String rw; // read/write status
public int type;
public JsonElement descr;
}
// Descriptor of dataPoint values
public static class Descr {
public int numStates;
public String[] states;
public String maxValue;
public String minValue;
}
// Array of UIDs with corresponding values, mapped into channel
public static class Dpval {
public int uid; // ID
public int value;
public int status;
}
}

View File

@@ -0,0 +1,499 @@
/**
* 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.core.thing.Thing.*;
import java.util.ArrayList;
import java.util.Collection;
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.function.Consumer;
import java.util.function.UnaryOperator;
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.gson.IntesisHomeJSonDTO.Data;
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Datapoints;
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Descr;
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Dp;
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Dpval;
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Id;
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Info;
import org.openhab.binding.intesis.internal.gson.IntesisHomeJSonDTO.Response;
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.State;
import org.openhab.core.types.StateOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
/**
* The {@link IntesisHomeHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Hans-Jörg Merk - Initial contribution
*/
@NonNullByDefault
public class IntesisHomeHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(IntesisHomeHandler.class);
private final IntesisHomeHttpApi api;
private final Map<String, String> properties = new HashMap<>();
private final IntesisDynamicStateDescriptionProvider intesisStateDescriptionProvider;
private final Gson gson = new Gson();
private IntesisConfiguration config = new IntesisConfiguration();
private @Nullable ScheduledFuture<?> refreshJob;
public IntesisHomeHandler(final Thing thing, final HttpClient httpClient,
IntesisDynamicStateDescriptionProvider intesisStateDescriptionProvider) {
super(thing);
this.api = new IntesisHomeHttpApi(config, httpClient);
this.intesisStateDescriptionProvider = intesisStateDescriptionProvider;
}
@Override
public void initialize() {
updateStatus(ThingStatus.UNKNOWN);
config = getConfigAs(IntesisConfiguration.class);
if (config.ipAddress.isEmpty() && config.password.isEmpty()) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "IP-Address and password not set");
return;
} else if (config.ipAddress.isEmpty()) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "IP-Address not set");
return;
} else if (config.password.isEmpty()) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Password not set");
return;
} else {
// start background initialization:
scheduler.submit(() -> {
populateProperties();
// query available dataPoints and build dynamic channels
postRequestInSession(sessionId -> "{\"command\":\"getavailabledatapoints\",\"data\":{\"sessionID\":\""
+ sessionId + "\"}}", this::handleDataPointsResponse);
updateProperties(properties);
});
}
}
@Override
public void dispose() {
logger.debug("IntesisHomeHandler disposed.");
final ScheduledFuture<?> refreshJob = this.refreshJob;
if (refreshJob != null) {
refreshJob.cancel(true);
this.refreshJob = null;
}
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
int uid = 0;
int value = 0;
String channelId = channelUID.getId();
if (command instanceof RefreshType) {
// Refresh command is not supported as the binding polls all values every 30 seconds
} else {
switch (channelId) {
case CHANNEL_TYPE_POWER:
uid = 1;
value = command.equals(OnOffType.OFF) ? 0 : 1;
break;
case CHANNEL_TYPE_MODE:
uid = 2;
value = IntesisHomeModeEnum.valueOf(command.toString()).getMode();
break;
case CHANNEL_TYPE_FANSPEED:
uid = 4;
if (("AUTO").equals(command.toString())) {
value = 0;
} else {
value = Integer.parseInt(command.toString());
}
break;
case CHANNEL_TYPE_VANESUD:
case CHANNEL_TYPE_VANESLR:
switch (command.toString()) {
case "AUTO":
value = 0;
break;
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
value = Integer.parseInt(command.toString());
break;
case "SWING":
value = 10;
break;
case "SWIRL":
value = 11;
break;
case "WIDE":
value = 12;
break;
}
switch (channelId) {
case CHANNEL_TYPE_VANESUD:
uid = 5;
break;
case CHANNEL_TYPE_VANESLR:
uid = 6;
break;
}
break;
case CHANNEL_TYPE_TARGETTEMP:
uid = 9;
if (command instanceof QuantityType) {
QuantityType<?> newVal = (QuantityType<?>) command;
newVal = newVal.toUnit(SIUnits.CELSIUS);
if (newVal != null) {
value = newVal.intValue() * 10;
}
}
break;
}
}
if (uid != 0) {
final int uId = uid;
final int newValue = value;
scheduler.submit(() -> {
postRequestInSession(
sessionId -> "{\"command\":\"setdatapointvalue\",\"data\":{\"sessionID\":\"" + sessionId
+ "\", \"uid\":" + uId + ",\"value\":" + newValue + "}}",
r -> updateStatus(ThingStatus.ONLINE));
});
}
}
public @Nullable String login() {
// lambda's can't modify local variables, so we use an array here to get around the issue
String[] sessionId = new String[1];
postRequest(
"{\"command\":\"login\",\"data\":{\"username\":\"Admin\",\"password\":\"" + config.password + "\"}}",
resp -> {
Data data = gson.fromJson(resp.data, Data.class);
Id id = gson.fromJson(data.id, Id.class);
sessionId[0] = id.sessionID.toString();
});
if (sessionId[0] != null && !sessionId[0].isEmpty()) {
updateStatus(ThingStatus.ONLINE);
return sessionId[0];
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "SessionId not received");
return null;
}
}
public @Nullable String logout(String sessionId) {
String contentString = "{\"command\":\"logout\",\"data\":{\"sessionID\":\"" + sessionId + "\"}}";
String response = api.postRequest(config.ipAddress, contentString);
return response;
}
public void populateProperties() {
postRequest("{\"command\":\"getinfo\",\"data\":\"\"}", resp -> {
Data data = gson.fromJson(resp.data, Data.class);
Info info = gson.fromJson(data.info, Info.class);
properties.put(PROPERTY_VENDOR, "Intesis");
properties.put(PROPERTY_MODEL_ID, info.deviceModel);
properties.put(PROPERTY_SERIAL_NUMBER, info.sn);
properties.put(PROPERTY_FIRMWARE_VERSION, info.fwVersion);
properties.put(PROPERTY_MAC_ADDRESS, info.wlanSTAMAC);
updateStatus(ThingStatus.ONLINE);
});
}
public void addChannel(String channelId, String itemType, @Nullable final Collection<String> options) {
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 (options != null) {
final List<StateOption> stateOptions = options.stream()
.map(e -> new StateOption(e, e.substring(0, 1) + e.substring(1).toLowerCase()))
.collect(Collectors.toList());
logger.trace("StateOptions : '{}'", stateOptions);
intesisStateDescriptionProvider.setStateOptions(channel.getUID(), stateOptions);
}
}
}
private void postRequest(String request, Consumer<Response> handler) {
try {
logger.trace("request : '{}'", request);
String response = api.postRequest(config.ipAddress, request);
if (response != null) {
Response resp = gson.fromJson(response, Response.class);
boolean success = resp.success;
if (success) {
handler.accept(resp);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Request unsuccessful");
}
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "No Response");
}
} catch (JsonSyntaxException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
}
}
private void postRequestInSession(UnaryOperator<String> requestFactory, Consumer<Response> handler) {
String sessionId = login();
if (sessionId != null) {
try {
String request = requestFactory.apply(sessionId);
postRequest(request, handler);
} finally {
logout(sessionId);
}
}
}
private void handleDataPointsResponse(Response response) {
try {
Data data = gson.fromJson(response.data, Data.class);
Dp dp = gson.fromJson(data.dp, Dp.class);
Datapoints[] datapoints = gson.fromJson(dp.datapoints, Datapoints[].class);
for (Datapoints datapoint : datapoints) {
Descr descr = gson.fromJson(datapoint.descr, Descr.class);
String channelId = "";
String itemType = "String";
switch (datapoint.uid) {
case 2:
List<String> opModes = new ArrayList<>();
for (String modString : descr.states) {
switch (modString) {
case "0":
opModes.add("AUTO");
break;
case "1":
opModes.add("HEAT");
break;
case "2":
opModes.add("DRY");
break;
case "3":
opModes.add("FAN");
break;
case "4":
opModes.add("COOL");
break;
}
}
properties.put("Supported modes", opModes.toString());
channelId = CHANNEL_TYPE_MODE;
addChannel(channelId, itemType, opModes);
break;
case 4:
List<String> fanLevels = new ArrayList<>();
for (String fanString : descr.states) {
if ("AUTO".contentEquals(fanString)) {
fanLevels.add("AUTO");
} else {
fanLevels.add(fanString);
}
}
properties.put("Supported fan levels", fanLevels.toString());
channelId = CHANNEL_TYPE_FANSPEED;
addChannel(channelId, itemType, fanLevels);
break;
case 5:
case 6:
List<String> swingModes = new ArrayList<>();
for (String swingString : descr.states) {
if ("AUTO".contentEquals(swingString)) {
swingModes.add("AUTO");
} else if ("10".contentEquals(swingString)) {
swingModes.add("SWING");
} else if ("11".contentEquals(swingString)) {
swingModes.add("SWIRL");
} else if ("12".contentEquals(swingString)) {
swingModes.add("WIDE");
} else {
swingModes.add(swingString);
}
}
switch (datapoint.uid) {
case 5:
channelId = CHANNEL_TYPE_VANESUD;
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());
addChannel(channelId, itemType, swingModes);
break;
}
break;
case 9:
channelId = CHANNEL_TYPE_TARGETTEMP;
itemType = "Number:Temperature";
addChannel(channelId, itemType, null);
break;
case 10:
channelId = CHANNEL_TYPE_AMBIENTTEMP;
itemType = "Number:Temperature";
addChannel(channelId, itemType, null);
break;
case 37:
channelId = CHANNEL_TYPE_OUTDOORTEMP;
itemType = "Number:Temperature";
addChannel(channelId, itemType, null);
break;
}
}
} catch (JsonSyntaxException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
}
logger.trace("Start Refresh Job");
refreshJob = scheduler.scheduleWithFixedDelay(this::getAllUidValues, 0, INTESIS_REFRESH_INTERVAL_SEC,
TimeUnit.SECONDS);
}
/**
* Update device status and all channels
*/
private void getAllUidValues() {
postRequestInSession(sessionId -> "{\"command\":\"getdatapointvalue\",\"data\":{\"sessionID\":\"" + sessionId
+ "\", \"uid\":\"all\"}}", this::handleDataPointValues);
}
private void handleDataPointValues(Response response) {
try {
Data data = gson.fromJson(response.data, Data.class);
Dpval[] dpval = gson.fromJson(data.dpval, Dpval[].class);
for (Dpval element : dpval) {
logger.trace("UID : {} ; value : {}", element.uid, element.value);
switch (element.uid) {
case 1:
updateState(CHANNEL_TYPE_POWER,
String.valueOf(element.value).equals("0") ? OnOffType.OFF : OnOffType.ON);
break;
case 2:
switch (element.value) {
case 0:
updateState(CHANNEL_TYPE_MODE, StringType.valueOf("AUTO"));
break;
case 1:
updateState(CHANNEL_TYPE_MODE, StringType.valueOf("HEAT"));
break;
case 2:
updateState(CHANNEL_TYPE_MODE, StringType.valueOf("DRY"));
break;
case 3:
updateState(CHANNEL_TYPE_MODE, StringType.valueOf("FAN"));
break;
case 4:
updateState(CHANNEL_TYPE_MODE, StringType.valueOf("COOL"));
break;
}
break;
case 4:
if ((element.value) == 0) {
updateState(CHANNEL_TYPE_FANSPEED, StringType.valueOf("AUTO"));
} else {
updateState(CHANNEL_TYPE_FANSPEED, StringType.valueOf(String.valueOf(element.value)));
}
break;
case 5:
case 6:
State state;
if ((element.value) == 0) {
state = StringType.valueOf("AUTO");
} else if ((element.value) == 10) {
state = StringType.valueOf("SWING");
} else if ((element.value) == 11) {
state = StringType.valueOf("SWIRL");
} else if ((element.value) == 12) {
state = StringType.valueOf("WIDE");
} else {
state = StringType.valueOf(String.valueOf(element.value));
}
switch (element.uid) {
case 5:
updateState(CHANNEL_TYPE_VANESUD, state);
break;
case 6:
updateState(CHANNEL_TYPE_VANESLR, state);
break;
}
break;
case 9:
int unit = Math.round((element.value) / 10);
State stateValue = QuantityType.valueOf(unit, SIUnits.CELSIUS);
updateState(CHANNEL_TYPE_TARGETTEMP, stateValue);
break;
case 10:
unit = Math.round((element.value) / 10);
stateValue = QuantityType.valueOf(unit, SIUnits.CELSIUS);
updateState(CHANNEL_TYPE_AMBIENTTEMP, stateValue);
break;
case 37:
unit = Math.round((element.value) / 10);
stateValue = QuantityType.valueOf(unit, SIUnits.CELSIUS);
updateState(CHANNEL_TYPE_OUTDOORTEMP, stateValue);
break;
}
}
} catch (JsonSyntaxException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
}
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="intesis" 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>Intesis Binding</name>
<description>This is the binding for Intesis WiFi adapters used in various AC devices.</description>
<author>Hans-Jörg Merk</author>
</binding:binding>

View File

@@ -0,0 +1,42 @@
# binding
binding.intesis.name = Intesis Binding
binding.intesis.description = This binding integrates Intesis WiFi devices to control various air conditioners
# thing types
thing-type.intesis.intesisHome.label = IntesisHome
thing-type.intesis.sample.description = IntesisHome WIFI adapter
# thing type config description
thing-type.config.intesis.ipAddress.label = IP Address
thing-type.config.intesis.ipAddress.description = IP Address of the Intesis device.
thing-type.config.intesisHome.password.label = Password
thing-type.config.intesisHome.password.description = Password to log into the IntesisHome device Web-Server.
# channel types
channel-type.intesis.power.label = Power
channel-type.intesis.power.description = Turn power on/off
channel-type.intesis.mode.label = Unit Mode
channel-type.intesis.mode.description = Operating mode of the Air Conditioner: AUTO/HEAT/DRY/FAN/COOL
channel-type.intesis.mode.state.option.auto = Auto
channel-type.intesis.mode.state.option.cool = Cool
channel-type.intesis.mode.state.option.dry = Dry
channel-type.intesis.mode.state.option.fan = Fan
channel-type.intesis.mode.state.option.heat = Heat
channel-type.intesis.targetTemperature.label = Target Temperature
channel-type.intesis.targetTemperature.description = Sets the desired room temperature.
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.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
channel-type.intesis.vanesUpDown.description = Sets the vertical (up/down)swing action on the Air Conditioner.
channel-type.intesis.vanesLeftRight.label = Horizontal Swing Mode
channel-type.intesis.vanesLeftRight.description = Sets the horizontal (left/right) swing action on the Air Conditioner.
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

View File

@@ -0,0 +1,42 @@
# binding
binding.intesis.name = Intesis Binding
binding.intesis.description = Das Intesis Binding integriert die Intesis WiFi Adapter, welche in diversen Klimageräten verwendet werden.
# thing types
thing-type.intesis.intesisHome.label = IntesisHome
thing-type.intesis.sample.description = IntesisHome WIFI Adapter
# thing type config description
thing-type.config.intesis.ipAddress.label = IP Addresse
thing-type.config.intesis.ipAddress.description = IP Addresse des Intesis Adapters.
thing-type.config.intesisHome.password.label = Passwort
thing-type.config.intesisHome.password.description = Password zum Login in den lokalen Web-Server des IntesisHome Adapters.
# channel types
channel-type.intesis.power.label = Betrieb
channel-type.intesis.power.description = Schaltet das Gerät Ein oder Aus.
channel-type.intesis.mode.label = Betriebsart
channel-type.intesis.mode.description = Betriebsart des Klimageräts: Auto/Heizen/Trocknen/Ventilation/Kühlen
channel-type.intesis.mode.state.option.auto = Auto
channel-type.intesis.mode.state.option.cool = Kühlen
channel-type.intesis.mode.state.option.dry = Trocknen
channel-type.intesis.mode.state.option.fan = Ventilation
channel-type.intesis.mode.state.option.heat = Heizen
channel-type.intesis.targetTemperature.label = SollTemperatur
channel-type.intesis.targetTemperature.description = Stellt die gewünschte Solltemperatur ein.
channel-type.intesis.ambientTemperature.label = Umgebungstemperatur
channel-type.intesis.ambientTemperature.description = Zeigt die aktuelle Raumtemperatur an.
channel-type.intesis.outdoorTemperature.label = Außentemperatur
channel-type.intesis.outdoorTemperature.description = Zeigt die aktuelle Außentemperatur an.
channel-type.intesis.fanSpeed.label = Ventilatorgeschwindigkeit
channel-type.intesis.fanSpeed.description = Stellt die gewüschte Ventilatorgeschwindigkeit des Klimageräts ein.
channel-type.intesis.fanSpeed.state.option.auto = Auto
channel-type.intesis.vanesUpDown.label = Vertikale (Auf/Ab) Lamelleneinstellung
channel-type.intesis.vanesUpDown.description = Stellt die vertikale Lamellensteuerung ein.
channel-type.intesis.vanesLeftRight.label = Horizontale (Links/Rechts) Lamelleneinstellung
channel-type.intesis.vanesLeftRight.description = Stellt die horizontale Lamellensteuerung ein.
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

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="intesis"
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">
<channel-type id="mode">
<item-type>String</item-type>
<label>@text/channel-type.intesis.mode.label</label>
<description>@text/channel-type.intesis.mode.description</description>
</channel-type>
<channel-type id="fanSpeed">
<item-type>String</item-type>
<label>@text/channel-type.intesis.fanSpeed.label</label>
<description>@text/channel-type.intesis.fanSpeed.description</description>
</channel-type>
<channel-type id="vanesUpDown">
<item-type>String</item-type>
<label>@text/channel-type.intesis.vanesUpDown.label</label>
<description>@text/channel-type.intesis.vanesUpDown.description</description>
</channel-type>
<channel-type id="vanesLeftRight">
<item-type>String</item-type>
<label>@text/channel-type.intesis.vanesLeftRight.label</label>
<description>@text/channel-type.intesis.vanesLeftRight.description</description>
</channel-type>
<channel-type id="targetTemperature">
<item-type>Number:Temperature</item-type>
<label>@text/channel-type.intesis.targetTemperature.label</label>
<description>@text/channel-type.intesis.targetTemperature.description</description>
<state pattern="%d %unit%"></state>
</channel-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="outdoorTemperature">
<item-type>Number:Temperature</item-type>
<label>@text/channel-type.intesis.outdoorTemperature.label</label>
<description>@text/channel-type.intesis.outdoorTemperature.description</description>
<state pattern="%d %unit%" readOnly="true"></state>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="intesis"
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="intesisHome">
<label>IntesisHome WiFi Adapter</label>
<description>IntesisHome WiFi Adapter</description>
<channels>
<channel id="power" typeId="system.power"/>
</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="password" type="text" required="true">
<label>@text/thing-type.config.intesisHome.password.label</label>
<description>@text/thing-type.config.intesisHome.password.description</description>
<context>password</context>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>