From 9b128c2f7de7a22e640c6dbd0c81e0a3ff7ed759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans-J=C3=B6rg=20Merk?= Date: Fri, 12 Aug 2022 10:51:42 +0200 Subject: [PATCH] Add RSSI channel to intesisHome and fixed some NPEs (#13244) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Hans-Jörg Merk --- bundles/org.openhab.binding.intesis/README.md | 2 +- .../internal/IntesisHandlerFactory.java | 3 - .../internal/handler/IntesisHomeHandler.java | 409 ++++++++++-------- .../resources/OH-INF/thing/thing-types.xml | 1 + 4 files changed, 236 insertions(+), 179 deletions(-) diff --git a/bundles/org.openhab.binding.intesis/README.md b/bundles/org.openhab.binding.intesis/README.md index 300c6b4b4..feed72209 100644 --- a/bundles/org.openhab.binding.intesis/README.md +++ b/bundles/org.openhab.binding.intesis/README.md @@ -42,7 +42,7 @@ The binding uses the following configuration parameters. | 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=very good, 2=good, 1=acceptable, 0=low | +| wifiSignal | Number | (Readonly) WiFi signal strength | 4=excellent, 3=very good, 2=good, 1=acceptable, 0=low | Note that individual A/C units may not support all channels, or all possible values for those channels. diff --git a/bundles/org.openhab.binding.intesis/src/main/java/org/openhab/binding/intesis/internal/IntesisHandlerFactory.java b/bundles/org.openhab.binding.intesis/src/main/java/org/openhab/binding/intesis/internal/IntesisHandlerFactory.java index 0bb2c6a5b..c35b8a472 100644 --- a/bundles/org.openhab.binding.intesis/src/main/java/org/openhab/binding/intesis/internal/IntesisHandlerFactory.java +++ b/bundles/org.openhab.binding.intesis/src/main/java/org/openhab/binding/intesis/internal/IntesisHandlerFactory.java @@ -34,8 +34,6 @@ 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 @@ -47,7 +45,6 @@ import org.slf4j.LoggerFactory; @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; diff --git a/bundles/org.openhab.binding.intesis/src/main/java/org/openhab/binding/intesis/internal/handler/IntesisHomeHandler.java b/bundles/org.openhab.binding.intesis/src/main/java/org/openhab/binding/intesis/internal/handler/IntesisHomeHandler.java index d4490e844..52f535c33 100644 --- a/bundles/org.openhab.binding.intesis/src/main/java/org/openhab/binding/intesis/internal/handler/IntesisHomeHandler.java +++ b/bundles/org.openhab.binding.intesis/src/main/java/org/openhab/binding/intesis/internal/handler/IntesisHomeHandler.java @@ -41,6 +41,7 @@ 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.DecimalType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringType; @@ -222,8 +223,12 @@ public class IntesisHomeHandler extends BaseThingHandler { "{\"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 (data != null) { + Id id = gson.fromJson(data.id, Id.class); + if (id != null) { + sessionId[0] = id.sessionID.toString(); + } + } }); if (sessionId[0] != null && !sessionId[0].isEmpty()) { updateStatus(ThingStatus.ONLINE); @@ -243,13 +248,45 @@ public class IntesisHomeHandler extends BaseThingHandler { 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); + if (data != null) { + Info info = gson.fromJson(data.info, Info.class); + if (info != null) { + 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 getWiFiSignal() { + postRequest("{\"command\":\"getinfo\",\"data\":\"\"}", resp -> { + Data data = gson.fromJson(resp.data, Data.class); + if (data != null) { + Info info = gson.fromJson(data.info, Info.class); + if (info != null) { + String rssi = info.rssi; + int dbm = Integer.valueOf(rssi); + 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; + } + DecimalType signalStrength = new DecimalType(strength); + updateState(CHANNEL_TYPE_RSSI, signalStrength); + + } + } }); } @@ -279,11 +316,14 @@ public class IntesisHomeHandler extends BaseThingHandler { 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"); + if (resp != null) { + 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"); @@ -308,105 +348,118 @@ public class IntesisHomeHandler extends BaseThingHandler { 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 opModes = new ArrayList<>(); - for (String modString : descr.states) { - switch (modString) { - case "0": - opModes.add("AUTO"); + if (data != null) { + Dp dp = gson.fromJson(data.dp, Dp.class); + if (dp != null) { + Datapoints[] datapoints = gson.fromJson(dp.datapoints, Datapoints[].class); + if (datapoints != null) { + for (Datapoints datapoint : datapoints) { + Descr descr = gson.fromJson(datapoint.descr, Descr.class); + String channelId = ""; + String itemType = "String"; + switch (datapoint.uid) { + case 2: + if (descr != null) { + List 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 "1": - opModes.add("HEAT"); + case 4: + if (descr != null) { + List 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 "2": - opModes.add("DRY"); + case 5: + case 6: + List swingModes = new ArrayList<>(); + if (descr != null) { + 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 "3": - opModes.add("FAN"); + case 9: + channelId = CHANNEL_TYPE_TARGETTEMP; + itemType = "Number:Temperature"; + addChannel(channelId, itemType, null); break; - case "4": - opModes.add("COOL"); + case 10: + channelId = CHANNEL_TYPE_AMBIENTTEMP; + itemType = "Number:Temperature"; + addChannel(channelId, itemType, null); + break; + case 14: + channelId = CHANNEL_TYPE_ERRORSTATUS; + itemType = "Switch"; + addChannel(channelId, itemType, null); + break; + case 15: + channelId = CHANNEL_TYPE_ERRORCODE; + itemType = "String"; + addChannel(channelId, itemType, null); + break; + case 37: + channelId = CHANNEL_TYPE_OUTDOORTEMP; + itemType = "Number:Temperature"; + addChannel(channelId, itemType, null); break; } } - properties.put("supported modes", opModes.toString()); - channelId = CHANNEL_TYPE_MODE; - addChannel(channelId, itemType, opModes); - break; - case 4: - List 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 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 14: - channelId = CHANNEL_TYPE_ERRORSTATUS; - itemType = "Switch"; - addChannel(channelId, itemType, null); - break; - case 15: - channelId = CHANNEL_TYPE_ERRORCODE; - itemType = "String"; - addChannel(channelId, itemType, null); - break; - case 37: - channelId = CHANNEL_TYPE_OUTDOORTEMP; - itemType = "Number:Temperature"; - addChannel(channelId, itemType, null); - break; + } } } } catch (JsonSyntaxException e) { @@ -423,90 +476,96 @@ public class IntesisHomeHandler extends BaseThingHandler { private void getAllUidValues() { postRequestInSession(sessionId -> "{\"command\":\"getdatapointvalue\",\"data\":{\"sessionID\":\"" + sessionId + "\", \"uid\":\"all\"}}", this::handleDataPointValues); + getWiFiSignal(); } 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; + if (data != null) { + Dpval[] dpval = gson.fromJson(data.dpval, Dpval[].class); + if (dpval != null) { + for (Dpval element : dpval) { + logger.trace("UID : {} ; value : {}", element.uid, element.value); + switch (element.uid) { case 1: - updateState(CHANNEL_TYPE_MODE, StringType.valueOf("HEAT")); + updateState(CHANNEL_TYPE_POWER, + String.valueOf(element.value).equals("0") ? OnOffType.OFF : OnOffType.ON); break; case 2: - updateState(CHANNEL_TYPE_MODE, StringType.valueOf("DRY")); - break; - case 3: - updateState(CHANNEL_TYPE_MODE, StringType.valueOf("FAN")); + 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: - updateState(CHANNEL_TYPE_MODE, StringType.valueOf("COOL")); + if ((element.value) == 0) { + updateState(CHANNEL_TYPE_FANSPEED, StringType.valueOf("AUTO")); + } else { + updateState(CHANNEL_TYPE_FANSPEED, + StringType.valueOf(String.valueOf(element.value))); + } 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); + 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 14: + updateState(CHANNEL_TYPE_ERRORSTATUS, + String.valueOf(element.value).equals("0") ? OnOffType.OFF : OnOffType.ON); + break; + case 15: + updateState(CHANNEL_TYPE_ERRORCODE, StringType.valueOf(String.valueOf(element.value))); + break; + case 37: + unit = Math.round((element.value) / 10); + stateValue = QuantityType.valueOf(unit, SIUnits.CELSIUS); + updateState(CHANNEL_TYPE_OUTDOORTEMP, stateValue); 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 14: - updateState(CHANNEL_TYPE_ERRORSTATUS, - String.valueOf(element.value).equals("0") ? OnOffType.OFF : OnOffType.ON); - break; - case 15: - updateState(CHANNEL_TYPE_ERRORCODE, StringType.valueOf(String.valueOf(element.value))); - break; - case 37: - unit = Math.round((element.value) / 10); - stateValue = QuantityType.valueOf(unit, SIUnits.CELSIUS); - updateState(CHANNEL_TYPE_OUTDOORTEMP, stateValue); - break; + } } } } catch (JsonSyntaxException e) { diff --git a/bundles/org.openhab.binding.intesis/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.intesis/src/main/resources/OH-INF/thing/thing-types.xml index b89de7883..32d2cef57 100644 --- a/bundles/org.openhab.binding.intesis/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.intesis/src/main/resources/OH-INF/thing/thing-types.xml @@ -9,6 +9,7 @@ Represents a single IntesisHome WiFi adapter on the network, connected to an A/C unit. +