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 1 commit
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
4 changes: 3 additions & 1 deletion bundles/org.openhab.binding.intesis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ The binding uses the following configuration parameters.

| Channel ID | Item Type | Description | Possible Values |
|--------------------|--------------------|--------------------------------------------------------|-----------------------------|
| power | Switch | Turns power on/off for your climate system. | ON, OFF |
| 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.

Expand Down
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;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ public class IntesisBoxMessage {
public static final String LIMITS = "LIMITS";
public static final String DISCOVER = "DISCOVER";

private static final Pattern REGEX = Pattern.compile(
"^(ID|INFO|SET|CHN|GET|LOGIN|LOGOUT|CFG|LIMITS)(?:,(\\d+))?:(APPVERSION|RUNVERSION|CFGVERSION|HASH|ONOFF|MODE|SETPTEMP|FANSP|VANEUD|VANELR|AMBTEMP|ERRSTATUS|ERRCODE),([A-Z0-9.,\\[\\]]+)$");
private static final Pattern REGEX = Pattern.compile("^([^,]+)(?:,(\\d+))?:([^,]+),([A-Z0-9.,\\[\\]]+)$");

@SuppressWarnings("unused")
private final String acNum;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@ public void openConnection() throws IOException {
IntesisBoxChangeListener listener = this.changeListener;
IntesisSocket localSocket = tcpSocket = new IntesisSocket();
tcpOutput = new OutputStreamWriter(localSocket.socket.getOutputStream(), "US-ASCII");
tcpInput = new BufferedReader(new InputStreamReader(localSocket.socket.getInputStream()));
tcpInput = new BufferedReader(new InputStreamReader(localSocket.socket.getInputStream(), "US-ASCII"));

Thread tcpListener = new Thread(new TCPListener());
tcpListener.setName("IntesisBoxTCPListener");
hmerk marked this conversation as resolved.
Show resolved Hide resolved
tcpListener.setDaemon(true);
tcpListener.start();

setConnected(true);
Expand Down Expand Up @@ -134,7 +136,6 @@ private void write(String data) {
tcpOutput.write(data);
}
if (tcpOutput != null) {
tcpOutput.flush();
}
} catch (IOException ioException) {
logger.debug("write(): {}", ioException.getMessage());
hmerk marked this conversation as resolved.
Show resolved Hide resolved
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@
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.IntesisBoxIdentity;
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.binding.intesis.internal.enums.IntesisBoxFunctionEnum;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
Expand Down Expand Up @@ -92,11 +90,15 @@ public void initialize() {
config = getConfigAs(IntesisBoxConfiguration.class);

if (!config.ipAddress.isEmpty()) {
intesisBoxSocketApi = new IntesisBoxSocketApi(config.ipAddress, config.port);
intesisBoxSocketApi.addIntesisBoxChangeListener(this);

updateStatus(ThingStatus.UNKNOWN);
scheduler.submit(() -> {
addChannel(CHANNEL_TYPE_AMBIENTTEMP, "Number:Temperature");
addChannel(CHANNEL_TYPE_ERRORCODE, "String");
addChannel(CHANNEL_TYPE_ERRORSTATUS, "String");
hmerk marked this conversation as resolved.
Show resolved Hide resolved

intesisBoxSocketApi = new IntesisBoxSocketApi(config.ipAddress, config.port);
intesisBoxSocketApi.addIntesisBoxChangeListener(this);
try {
if (intesisBoxSocketApi != null) {
intesisBoxSocketApi.openConnection();
Expand Down Expand Up @@ -166,9 +168,11 @@ public void handleCommand(ChannelUID channelUID, Command command) {
}
}
String value = "";
String function = "";
switch (channelUID.getId()) {
case CHANNEL_TYPE_POWER:
if (command instanceof OnOffType) {
function = "ONOFF";
value = command == OnOffType.ON ? "ON" : "OFF";
}
break;
Expand All @@ -181,19 +185,29 @@ public void handleCommand(ChannelUID channelUID, Command command) {
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()) {
String function = IntesisBoxFunctionEnum.valueOf(channelUID.getId()).getFunction();
if (!value.isEmpty() || function.isEmpty()) {
if (api != null) {
logger.trace("Sending command {} to function {}", value, function);
api.sendCommand(function, value);
Expand All @@ -203,32 +217,17 @@ public void handleCommand(ChannelUID channelUID, Command command) {
}
}

private void receivedId(String function, String value) {
logger.trace("receivedID(): {} {}", function, value);
private void populateProperties(String data) {
String[] value = data.substring(3).split(",");
properties.put(PROPERTY_VENDOR, "Intesis");
switch (function) {
case "MODEL":
properties.put(PROPERTY_MODEL_ID, value);
break;
case "MAC":
properties.put(PROPERTY_MAC_ADDRESS, value);
break;
case "IP":
properties.put("ipAddress", value);
case "PROTOCOL":
properties.put("protocol", value);
break;
case "VERSION":
properties.put(PROPERTY_FIRMWARE_VERSION, value);
break;
case "RSSI":
properties.put("rssi", value);
break;
case "NAME":
properties.put("hostname", value);
break;
}
logger.trace("Update Properties for ID : {}", properties);
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("rssi", value[5]);
hmerk marked this conversation as resolved.
Show resolved Hide resolved
properties.put("hostname", value[6]);
updateProperties(properties);
}

private void receivedUpdate(String function, String receivedValue) {
Expand Down Expand Up @@ -287,54 +286,48 @@ private void handleMessage(String data) {
return;
}
if (data.startsWith(ID + ':')) {
synchronized (this) {
new IntesisBoxIdentity(data).value.forEach((name, value) -> receivedId(name, value));
return;
}
populateProperties(data);
return;
}
IntesisBoxMessage message = IntesisBoxMessage.parse(data);
if (message.getCommand() != null) {
switch (message.getCommand()) {
case LIMITS:
logger.debug("handleMessage(): Limits received - {}", data);
synchronized (this) {
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;
}
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;
}
addChannel(CHANNEL_TYPE_AMBIENTTEMP, "Number:Temperature");

}
updateProperties(properties);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Loading