]> git.basschouten.com Git - openhab-addons.git/commitdiff
[radiothermostat] Add Remote Temperature channel (#10194)
authormlobstein <michael.lobstein@gmail.com>
Fri, 9 Apr 2021 21:28:38 +0000 (16:28 -0500)
committerGitHub <noreply@github.com>
Fri, 9 Apr 2021 21:28:38 +0000 (23:28 +0200)
* Add Remote Temperature channel

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
* Fix spelling error

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
* Fix spelling error2

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
* review changes

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
* review changes

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
* review changes

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
* minor README update

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
bundles/org.openhab.binding.radiothermostat/README.md
bundles/org.openhab.binding.radiothermostat/doc/index.jpg [new file with mode: 0644]
bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/RadioThermostatBindingConstants.java
bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/communication/RadioThermostatConnector.java
bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/discovery/RadioThermostatDiscoveryService.java
bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/handler/RadioThermostatHandler.java
bundles/org.openhab.binding.radiothermostat/src/main/resources/OH-INF/thing/thing-types.xml

index 74987466aae420a9b90c041685fb2ecfaf4863da..e5244c0de7aca9a712cbc8c4a21e992bba1b9475 100644 (file)
@@ -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]" <temperature>     { 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 (file)
index 0000000..963f529
Binary files /dev/null and b/bundles/org.openhab.binding.radiothermostat/doc/index.jpg differ
index 64bed1aed37bb2ead4835b3da51ee8a4eb07ff45..daf02d99e749f212dd335ca7a73edf5064b66a2e 100644 (file)
@@ -47,6 +47,7 @@ public class RadioThermostatBindingConstants {
     public static final String DEFAULT_RESOURCE = "tstat";
     public static final String RUNTIME_RESOURCE = "tstat/datalog";
     public static final String HUMIDITY_RESOURCE = "tstat/humidity";
+    public static final String REMOTE_TEMP_RESOURCE = "tstat/remote_temp";
 
     // List of all Thing Type UIDs
     public static final ThingTypeUID THING_TYPE_RTHERM = new ThingTypeUID(BINDING_ID, "rtherm");
@@ -70,11 +71,12 @@ public class RadioThermostatBindingConstants {
     public static final String TODAY_COOL_RUNTIME = "today_cool_runtime";
     public static final String YESTERDAY_HEAT_RUNTIME = "yesterday_heat_runtime";
     public static final String YESTERDAY_COOL_RUNTIME = "yesterday_cool_runtime";
+    public static final String REMOTE_TEMP = "remote_temp";
 
     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_RTHERM);
     public static final Set<String> 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
index fb25804f435fc678b57084b51f12ef87938e0185..78646d41416b3b9bf78aedeec0dbbd374984628d 100644 (file)
@@ -105,10 +105,11 @@ public class RadioThermostatConnector {
      *
      * @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 class RadioThermostatConnector {
      * @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 = "";
 
index 4c276eb6f867eb972c238bb3a7db758891dc6870..250f9251cea1cc7d6fbd057d47295b0d367f430e 100644 (file)
@@ -81,11 +81,12 @@ public class RadioThermostatDiscoveryService extends AbstractDiscoveryService {
                 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;
         }
     }
 
index b9b2bbaee80c32c2701e66822d4c2b172bc1475a..6ab451829938d778aa2842487f5d1d34736f365c 100644 (file)
@@ -46,6 +46,7 @@ import org.openhab.core.library.types.OnOffType;
 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 class RadioThermostatHandler extends BaseThingHandler implements RadioThe
     }
 
     public void handleRawCommand(@Nullable String rawCommand) {
-        connector.sendCommand(null, null, rawCommand);
+        connector.sendCommand(null, null, rawCommand, DEFAULT_RESOURCE);
     }
 
     @Override
@@ -226,21 +227,19 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
         } 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 class RadioThermostatHandler extends BaseThingHandler implements RadioThe
                         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 class RadioThermostatHandler extends BaseThingHandler implements RadioThe
                         // 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<Temperature>) 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 class RadioThermostatHandler extends BaseThingHandler implements RadioThe
                     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 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
 
     /**
      * 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 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
 
     /**
      * Build a list of fan modes based on what model thermostat is used
-     * 
+     *
      * @return list of state options for thermostat fan modes
      */
     private List<StateOption> getFanModeOptions() {
index 557d36c560bbeaeee5112492eb49b3ebb3e58de5..a33622dbdc557e38347178f0c9a03aa198ee93bd 100644 (file)
@@ -22,6 +22,7 @@
                        <channel id="hold" typeId="hold"/>
                        <channel id="status" typeId="status"/>
                        <channel id="fan_status" typeId="fan_status"/>
+                       <channel id="remote_temp" typeId="remote_temp"/>
                        <channel id="day" typeId="t_day"/>
                        <channel id="hour" typeId="t_hour"/>
                        <channel id="minute" typeId="t_minute"/>
                <state min="0" max="2" pattern="%d"/>
        </channel-type>
 
+       <channel-type id="remote_temp" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Remote Temperature</label>
+               <description>The remote temperature takes the place of the ambient temperature as read by the local thermostat
+                       temperature sensor</description>
+               <state pattern="%d %unit%"/>
+       </channel-type>
+
        <channel-type id="t_day" advanced="true">
                <item-type>Number</item-type>
                <label>Day</label>