From 035556bc55a6db15e1999204ee6b60b4570a347b Mon Sep 17 00:00:00 2001 From: mlobstein Date: Fri, 9 Apr 2021 16:28:38 -0500 Subject: [PATCH] [radiothermostat] Add Remote Temperature channel (#10194) * Add Remote Temperature channel Signed-off-by: Michael Lobstein * Fix spelling error Signed-off-by: Michael Lobstein * Fix spelling error2 Signed-off-by: Michael Lobstein * review changes Signed-off-by: Michael Lobstein * review changes Signed-off-by: Michael Lobstein * review changes Signed-off-by: Michael Lobstein * minor README update Signed-off-by: Michael Lobstein --- .../README.md | 53 ++++++++++-------- .../doc/index.jpg | Bin 0 -> 10950 bytes .../RadioThermostatBindingConstants.java | 4 +- .../RadioThermostatConnector.java | 11 ++-- .../RadioThermostatDiscoveryService.java | 5 +- .../handler/RadioThermostatHandler.java | 49 +++++++++------- .../resources/OH-INF/thing/thing-types.xml | 9 +++ 7 files changed, 83 insertions(+), 48 deletions(-) create mode 100644 bundles/org.openhab.binding.radiothermostat/doc/index.jpg diff --git a/bundles/org.openhab.binding.radiothermostat/README.md b/bundles/org.openhab.binding.radiothermostat/README.md index 74987466aae42..e5244c0de7aca 100644 --- a/bundles/org.openhab.binding.radiothermostat/README.md +++ b/bundles/org.openhab.binding.radiothermostat/README.md @@ -1,5 +1,7 @@ # RadioThermostat Binding +![RadioThermostat logo](doc/index.jpg) + This binding connects RadioThermostat/3M Filtrete models CT30, CT50/3M50, CT80, etc. with built-in Wi-Fi module to openHAB. The binding retrieves and periodically updates all basic system information from the thermostat. @@ -45,26 +47,27 @@ The thing has a few configuration parameters: The thermostat information that is retrieved is available as these channels: -| Channel ID | Item Type | Description | -|------------------------|----------------------|---------------------------------------------------------------------------| -| temperature | Number:Temperature | The current temperature reading of the thermostat | -| humidity | Number:Dimensionless | The current humidity reading of the thermostat (CT80 only) | -| mode | Number | The current operating mode of the HVAC system | -| fan_mode | Number | The current operating mode of the fan | -| program_mode | Number | The program schedule that the thermostat is running (CT80 Rev B only) | -| set_point | Number:Temperature | The current temperature set point of the thermostat | -| status | Number | Indicates the current running status of the HVAC system | -| fan_status | Number | Indicates the current fan status of the HVAC system | -| override | Number | Indicates if the normal program set-point has been manually overridden | -| hold | Switch | Indicates if the current set point temperature is to be held indefinitely | -| day | Number | The current day of the week reported by the thermostat (0 = Monday) | -| hour | Number | The current hour of the day reported by the thermostat (24 hr) | -| minute | Number | The current minute past the hour reported by the thermostat | -| dt_stamp | String | The current day of the week and time reported by the thermostat (E HH:mm) | -| today_heat_runtime | Number:Time | The total number of minutes of heating run-time today | -| today_cool_runtime | Number:Time | The total number of minutes of cooling run-time today | -| yesterday_heat_runtime | Number:Time | The total number of minutes of heating run-time yesterday | -| yesterday_cool_runtime | Number:Time | The total number of minutes of cooling run-time yesterday | +| Channel ID | Item Type | Description | +|------------------------|----------------------|------------------------------------------------------------------------------------------------------------------------------------| +| temperature | Number:Temperature | The current temperature reading of the thermostat | +| humidity | Number:Dimensionless | The current humidity reading of the thermostat (CT80 only) | +| mode | Number | The current operating mode of the HVAC system | +| fan_mode | Number | The current operating mode of the fan | +| program_mode | Number | The program schedule that the thermostat is running (CT80 Rev B only) | +| set_point | Number:Temperature | The current temperature set point of the thermostat | +| status | Number | Indicates the current running status of the HVAC system | +| fan_status | Number | Indicates the current fan status of the HVAC system | +| override | Number | Indicates if the normal program set-point has been manually overridden | +| hold | Switch | Indicates if the current set point temperature is to be held indefinitely | +| remote_temp | Number:Temperature | Override the internal temperature as read by the thermostat's temperature sensor; Set to -1 to return to internal temperature mode | +| day | Number | The current day of the week reported by the thermostat (0 = Monday) | +| hour | Number | The current hour of the day reported by the thermostat (24 hr) | +| minute | Number | The current minute past the hour reported by the thermostat | +| dt_stamp | String | The current day of the week and time reported by the thermostat (E HH:mm) | +| today_heat_runtime | Number:Time | The total number of minutes of heating run-time today | +| today_cool_runtime | Number:Time | The total number of minutes of cooling run-time today | +| yesterday_heat_runtime | Number:Time | The total number of minutes of heating run-time yesterday | +| yesterday_cool_runtime | Number:Time | The total number of minutes of cooling run-time yesterday | ## Full Example @@ -145,6 +148,9 @@ Number:Time Therm_todaycool "Today's Cooling Runtime [%d %unit%]" { channe Number:Time Therm_yesterdayheat "Yesterday's Heating Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:yesterday_heat_runtime" } Number:Time Therm_yesterdaycool "Yesterday's Cooling Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:yesterday_cool_runtime" } +// Override the thermostat's temperature reading with a value from an external sensor, set to -1 to revert to internal temperature mode +Number:Temperature Therm_Rtemp "Remote Temperature [%d]" { channel="radiothermostat:rtherm:mytherm1:remote_temp" } + // A virtual switch used to trigger a rule to send a json command to the thermostat Switch Therm_mysetting "Send my preferred setting" ``` @@ -167,9 +173,12 @@ sitemap radiotherm label="My Thermostat" { Text item=Therm_Override icon="smoke" Switch item=Therm_Hold icon="smoke" + // Example of overriding the thermostat's temperature reading + Switch item=Therm_Rtemp label="Remote Temp" icon="temperature" mappings=[60="60", 75="75", 80="80", -1="Reset"] + // Virtual switch/button to trigger a rule to send a custom command // The ON value displays in the button - Switch item=Therm_mysetting mappings=[ON="Heat, 58, hold"] + Switch item=Therm_mysetting mappings=[ON="Heat, 68, hold"] Text item=Therm_Day Text item=Therm_Hour @@ -198,6 +207,6 @@ then } // JSON to send directly to the thermostat's '/tstat' endpoint // See RadioThermostat_CT50_Honeywell_Wifi_API_V1.3.pdf for more detail - actions.sendRawCommand('{"hold":1, "t_heat":' + "58" + ', "tmode":1}') + actions.sendRawCommand('{"hold":1, "t_heat":' + "68" + ', "tmode":1}') end ``` diff --git a/bundles/org.openhab.binding.radiothermostat/doc/index.jpg b/bundles/org.openhab.binding.radiothermostat/doc/index.jpg new file mode 100644 index 0000000000000000000000000000000000000000..963f5295621ef541b1a27b43925a219da6c4cc4c GIT binary patch literal 10950 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 uyv~ylsHFTC%>O;&zf$|( SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_RTHERM); public static final Set SUPPORTED_CHANNEL_IDS = Stream.of(TEMPERATURE, HUMIDITY, MODE, FAN_MODE, PROGRAM_MODE, SET_POINT, OVERRIDE, HOLD, STATUS, FAN_STATUS, DAY, HOUR, MINUTE, DATE_STAMP, - TODAY_HEAT_RUNTIME, TODAY_COOL_RUNTIME, YESTERDAY_HEAT_RUNTIME, YESTERDAY_COOL_RUNTIME) + TODAY_HEAT_RUNTIME, TODAY_COOL_RUNTIME, YESTERDAY_HEAT_RUNTIME, YESTERDAY_COOL_RUNTIME, REMOTE_TEMP) .collect(Collectors.toSet()); // Units of measurement of the data delivered by the API diff --git a/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/communication/RadioThermostatConnector.java b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/communication/RadioThermostatConnector.java index fb25804f435fc..78646d41416b3 100644 --- a/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/communication/RadioThermostatConnector.java +++ b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/communication/RadioThermostatConnector.java @@ -105,10 +105,11 @@ public void onComplete(@Nullable Result result) { * * @param the JSON attribute key for the value to be updated * @param the value to be updated in the thermostat + * @param the end point URI to use for the command * @return the JSON response string from the thermostat */ - public String sendCommand(String cmdKey, @Nullable String cmdVal) { - return sendCommand(cmdKey, cmdVal, null); + public String sendCommand(String cmdKey, @Nullable String cmdVal, String resource) { + return sendCommand(cmdKey, cmdVal, null, resource); } /** @@ -117,12 +118,14 @@ public String sendCommand(String cmdKey, @Nullable String cmdVal) { * @param the JSON attribute key for the value to be updated * @param the value to be updated in the thermostat * @param JSON string to send directly to the thermostat instead of a key/value pair + * @param the end point URI to use for the command * @return the JSON response string from the thermostat */ - public String sendCommand(@Nullable String cmdKey, @Nullable String cmdVal, @Nullable String cmdJson) { + public String sendCommand(@Nullable String cmdKey, @Nullable String cmdVal, @Nullable String cmdJson, + String resource) { // if we got a cmdJson string send that, otherwise build the json from the key and val params String postJson = cmdJson != null ? cmdJson : "{\"" + cmdKey + "\":" + cmdVal + "}"; - String urlStr = buildRequestURL(DEFAULT_RESOURCE); + String urlStr = buildRequestURL(resource); String output = ""; diff --git a/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/discovery/RadioThermostatDiscoveryService.java b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/discovery/RadioThermostatDiscoveryService.java index 4c276eb6f867e..250f9251cea1c 100644 --- a/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/discovery/RadioThermostatDiscoveryService.java +++ b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/discovery/RadioThermostatDiscoveryService.java @@ -81,11 +81,12 @@ protected void startBackgroundDiscovery() { TimeUnit.SECONDS); } - @SuppressWarnings("null") @Override protected void stopBackgroundDiscovery() { - if (scheduledFuture != null && !scheduledFuture.isCancelled()) { + ScheduledFuture scheduledFuture = this.scheduledFuture; + if (scheduledFuture != null) { scheduledFuture.cancel(true); + this.scheduledFuture = null; } } diff --git a/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/handler/RadioThermostatHandler.java b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/handler/RadioThermostatHandler.java index b9b2bbaee80c3..6ab451829938d 100644 --- a/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/handler/RadioThermostatHandler.java +++ b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/handler/RadioThermostatHandler.java @@ -46,6 +46,7 @@ import org.openhab.core.library.types.PointType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.ImperialUnits; import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -216,7 +217,7 @@ public void dispose() { } public void handleRawCommand(@Nullable String rawCommand) { - connector.sendCommand(null, null, rawCommand); + connector.sendCommand(null, null, rawCommand, DEFAULT_RESOURCE); } @Override @@ -226,21 +227,19 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else { Integer cmdInt = -1; String cmdStr = command.toString(); - if (cmdStr != null) { - try { - // parse out an Integer from the string - // ie '70.5 F' becomes 70, also handles negative numbers - cmdInt = NumberFormat.getInstance().parse(cmdStr).intValue(); - } catch (ParseException e) { - logger.debug("Command: {} -> Not an integer", cmdStr); - } + try { + // parse out an Integer from the string + // ie '70.5 F' becomes 70, also handles negative numbers + cmdInt = NumberFormat.getInstance().parse(cmdStr).intValue(); + } catch (ParseException e) { + logger.debug("Command: {} -> Not an integer", cmdStr); } switch (channelUID.getId()) { case MODE: // only do if commanded mode is different than current mode if (!cmdInt.equals(rthermData.getThermostatData().getMode())) { - connector.sendCommand("tmode", cmdStr); + connector.sendCommand("tmode", cmdStr, DEFAULT_RESOURCE); // set the new operating mode, reset everything else, // because refreshing the tstat data below is really slow. @@ -253,26 +252,26 @@ public void handleCommand(ChannelUID channelUID, Command command) { rthermData.getThermostatData().setProgramMode(-1); updateChannel(PROGRAM_MODE, rthermData); - // now just trigger a refresh of the thermost to get the new active setpoint + // now just trigger a refresh of the thermostat to get the new active setpoint // this takes a while for the JSON request to complete (async). connector.getAsyncThermostatData(DEFAULT_RESOURCE); } break; case FAN_MODE: rthermData.getThermostatData().setFanMode(cmdInt); - connector.sendCommand("fmode", cmdStr); + connector.sendCommand("fmode", cmdStr, DEFAULT_RESOURCE); break; case PROGRAM_MODE: rthermData.getThermostatData().setProgramMode(cmdInt); - connector.sendCommand("program_mode", cmdStr); + connector.sendCommand("program_mode", cmdStr, DEFAULT_RESOURCE); break; case HOLD: if (command instanceof OnOffType && command == OnOffType.ON) { rthermData.getThermostatData().setHold(1); - connector.sendCommand("hold", "1"); + connector.sendCommand("hold", "1", DEFAULT_RESOURCE); } else if (command instanceof OnOffType && command == OnOffType.OFF) { rthermData.getThermostatData().setHold(0); - connector.sendCommand("hold", "0"); + connector.sendCommand("hold", "0", DEFAULT_RESOURCE); } break; case SET_POINT: @@ -287,7 +286,16 @@ public void handleCommand(ChannelUID channelUID, Command command) { // don't do anything if we are not in heat or cool mode break; } - connector.sendCommand(cmdKey, cmdInt.toString()); + connector.sendCommand(cmdKey, cmdInt.toString(), DEFAULT_RESOURCE); + break; + case REMOTE_TEMP: + if (cmdInt != -1) { + QuantityType remoteTemp = ((QuantityType) command) + .toUnit(ImperialUnits.FAHRENHEIT); + connector.sendCommand("rem_temp", String.valueOf(remoteTemp.intValue()), REMOTE_TEMP_RESOURCE); + } else { + connector.sendCommand("rem_mode", "0", REMOTE_TEMP_RESOURCE); + } break; default: logger.warn("Unsupported command: {}", command.toString()); @@ -320,7 +328,10 @@ public void onNewMessageEvent(RadioThermostatEvent event) { updateAllChannels(); break; case HUMIDITY_RESOURCE: - rthermData.setHumidity(gson.fromJson(evtVal, RadioThermostatHumidityDTO.class).getHumidity()); + RadioThermostatHumidityDTO dto = gson.fromJson(evtVal, RadioThermostatHumidityDTO.class); + if (dto != null) { + rthermData.setHumidity(dto.getHumidity()); + } updateChannel(HUMIDITY, rthermData); break; case RUNTIME_RESOURCE: @@ -382,7 +393,7 @@ private void updateChannel(String channelId, RadioThermostatDTO rthermData) { /** * Update a given channelId from the thermostat data - * + * * @param the channel id to be updated * @param data the RadioThermostat dto * @return the value to be set in the state @@ -456,7 +467,7 @@ private void updateAllChannels() { /** * Build a list of fan modes based on what model thermostat is used - * + * * @return list of state options for thermostat fan modes */ private List getFanModeOptions() { diff --git a/bundles/org.openhab.binding.radiothermostat/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.radiothermostat/src/main/resources/OH-INF/thing/thing-types.xml index 557d36c560bbe..a33622dbdc557 100644 --- a/bundles/org.openhab.binding.radiothermostat/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.radiothermostat/src/main/resources/OH-INF/thing/thing-types.xml @@ -22,6 +22,7 @@ + @@ -157,6 +158,14 @@ + + Number:Temperature + + The remote temperature takes the place of the ambient temperature as read by the local thermostat + temperature sensor + + + Number