Skip to content

Commit 035556b

Browse files
authored
[radiothermostat] Add Remote Temperature channel (openhab#10194)
* Add Remote Temperature channel Signed-off-by: Michael Lobstein <[email protected]> * Fix spelling error Signed-off-by: Michael Lobstein <[email protected]> * Fix spelling error2 Signed-off-by: Michael Lobstein <[email protected]> * review changes Signed-off-by: Michael Lobstein <[email protected]> * review changes Signed-off-by: Michael Lobstein <[email protected]> * review changes Signed-off-by: Michael Lobstein <[email protected]> * minor README update Signed-off-by: Michael Lobstein <[email protected]>
1 parent 3561388 commit 035556b

File tree

7 files changed

+83
-48
lines changed

7 files changed

+83
-48
lines changed

bundles/org.openhab.binding.radiothermostat/README.md

+31-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# RadioThermostat Binding
22

3+
![RadioThermostat logo](doc/index.jpg)
4+
35
This binding connects RadioThermostat/3M Filtrete models CT30, CT50/3M50, CT80, etc. with built-in Wi-Fi module to openHAB.
46

57
The binding retrieves and periodically updates all basic system information from the thermostat.
@@ -45,26 +47,27 @@ The thing has a few configuration parameters:
4547

4648
The thermostat information that is retrieved is available as these channels:
4749

48-
| Channel ID | Item Type | Description |
49-
|------------------------|----------------------|---------------------------------------------------------------------------|
50-
| temperature | Number:Temperature | The current temperature reading of the thermostat |
51-
| humidity | Number:Dimensionless | The current humidity reading of the thermostat (CT80 only) |
52-
| mode | Number | The current operating mode of the HVAC system |
53-
| fan_mode | Number | The current operating mode of the fan |
54-
| program_mode | Number | The program schedule that the thermostat is running (CT80 Rev B only) |
55-
| set_point | Number:Temperature | The current temperature set point of the thermostat |
56-
| status | Number | Indicates the current running status of the HVAC system |
57-
| fan_status | Number | Indicates the current fan status of the HVAC system |
58-
| override | Number | Indicates if the normal program set-point has been manually overridden |
59-
| hold | Switch | Indicates if the current set point temperature is to be held indefinitely |
60-
| day | Number | The current day of the week reported by the thermostat (0 = Monday) |
61-
| hour | Number | The current hour of the day reported by the thermostat (24 hr) |
62-
| minute | Number | The current minute past the hour reported by the thermostat |
63-
| dt_stamp | String | The current day of the week and time reported by the thermostat (E HH:mm) |
64-
| today_heat_runtime | Number:Time | The total number of minutes of heating run-time today |
65-
| today_cool_runtime | Number:Time | The total number of minutes of cooling run-time today |
66-
| yesterday_heat_runtime | Number:Time | The total number of minutes of heating run-time yesterday |
67-
| yesterday_cool_runtime | Number:Time | The total number of minutes of cooling run-time yesterday |
50+
| Channel ID | Item Type | Description |
51+
|------------------------|----------------------|------------------------------------------------------------------------------------------------------------------------------------|
52+
| temperature | Number:Temperature | The current temperature reading of the thermostat |
53+
| humidity | Number:Dimensionless | The current humidity reading of the thermostat (CT80 only) |
54+
| mode | Number | The current operating mode of the HVAC system |
55+
| fan_mode | Number | The current operating mode of the fan |
56+
| program_mode | Number | The program schedule that the thermostat is running (CT80 Rev B only) |
57+
| set_point | Number:Temperature | The current temperature set point of the thermostat |
58+
| status | Number | Indicates the current running status of the HVAC system |
59+
| fan_status | Number | Indicates the current fan status of the HVAC system |
60+
| override | Number | Indicates if the normal program set-point has been manually overridden |
61+
| hold | Switch | Indicates if the current set point temperature is to be held indefinitely |
62+
| 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 |
63+
| day | Number | The current day of the week reported by the thermostat (0 = Monday) |
64+
| hour | Number | The current hour of the day reported by the thermostat (24 hr) |
65+
| minute | Number | The current minute past the hour reported by the thermostat |
66+
| dt_stamp | String | The current day of the week and time reported by the thermostat (E HH:mm) |
67+
| today_heat_runtime | Number:Time | The total number of minutes of heating run-time today |
68+
| today_cool_runtime | Number:Time | The total number of minutes of cooling run-time today |
69+
| yesterday_heat_runtime | Number:Time | The total number of minutes of heating run-time yesterday |
70+
| yesterday_cool_runtime | Number:Time | The total number of minutes of cooling run-time yesterday |
6871

6972
## Full Example
7073

@@ -145,6 +148,9 @@ Number:Time Therm_todaycool "Today's Cooling Runtime [%d %unit%]" { channe
145148
Number:Time Therm_yesterdayheat "Yesterday's Heating Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:yesterday_heat_runtime" }
146149
Number:Time Therm_yesterdaycool "Yesterday's Cooling Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:yesterday_cool_runtime" }
147150

151+
// Override the thermostat's temperature reading with a value from an external sensor, set to -1 to revert to internal temperature mode
152+
Number:Temperature Therm_Rtemp "Remote Temperature [%d]" <temperature> { channel="radiothermostat:rtherm:mytherm1:remote_temp" }
153+
148154
// A virtual switch used to trigger a rule to send a json command to the thermostat
149155
Switch Therm_mysetting "Send my preferred setting"
150156
```
@@ -167,9 +173,12 @@ sitemap radiotherm label="My Thermostat" {
167173
Text item=Therm_Override icon="smoke"
168174
Switch item=Therm_Hold icon="smoke"
169175

176+
// Example of overriding the thermostat's temperature reading
177+
Switch item=Therm_Rtemp label="Remote Temp" icon="temperature" mappings=[60="60", 75="75", 80="80", -1="Reset"]
178+
170179
// Virtual switch/button to trigger a rule to send a custom command
171180
// The ON value displays in the button
172-
Switch item=Therm_mysetting mappings=[ON="Heat, 58, hold"]
181+
Switch item=Therm_mysetting mappings=[ON="Heat, 68, hold"]
173182
174183
Text item=Therm_Day
175184
Text item=Therm_Hour
@@ -198,6 +207,6 @@ then
198207
}
199208
// JSON to send directly to the thermostat's '/tstat' endpoint
200209
// See RadioThermostat_CT50_Honeywell_Wifi_API_V1.3.pdf for more detail
201-
actions.sendRawCommand('{"hold":1, "t_heat":' + "58" + ', "tmode":1}')
210+
actions.sendRawCommand('{"hold":1, "t_heat":' + "68" + ', "tmode":1}')
202211
end
203212
```
Loading

bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/RadioThermostatBindingConstants.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class RadioThermostatBindingConstants {
4747
public static final String DEFAULT_RESOURCE = "tstat";
4848
public static final String RUNTIME_RESOURCE = "tstat/datalog";
4949
public static final String HUMIDITY_RESOURCE = "tstat/humidity";
50+
public static final String REMOTE_TEMP_RESOURCE = "tstat/remote_temp";
5051

5152
// List of all Thing Type UIDs
5253
public static final ThingTypeUID THING_TYPE_RTHERM = new ThingTypeUID(BINDING_ID, "rtherm");
@@ -70,11 +71,12 @@ public class RadioThermostatBindingConstants {
7071
public static final String TODAY_COOL_RUNTIME = "today_cool_runtime";
7172
public static final String YESTERDAY_HEAT_RUNTIME = "yesterday_heat_runtime";
7273
public static final String YESTERDAY_COOL_RUNTIME = "yesterday_cool_runtime";
74+
public static final String REMOTE_TEMP = "remote_temp";
7375

7476
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_RTHERM);
7577
public static final Set<String> SUPPORTED_CHANNEL_IDS = Stream.of(TEMPERATURE, HUMIDITY, MODE, FAN_MODE,
7678
PROGRAM_MODE, SET_POINT, OVERRIDE, HOLD, STATUS, FAN_STATUS, DAY, HOUR, MINUTE, DATE_STAMP,
77-
TODAY_HEAT_RUNTIME, TODAY_COOL_RUNTIME, YESTERDAY_HEAT_RUNTIME, YESTERDAY_COOL_RUNTIME)
79+
TODAY_HEAT_RUNTIME, TODAY_COOL_RUNTIME, YESTERDAY_HEAT_RUNTIME, YESTERDAY_COOL_RUNTIME, REMOTE_TEMP)
7880
.collect(Collectors.toSet());
7981

8082
// Units of measurement of the data delivered by the API

bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/communication/RadioThermostatConnector.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,11 @@ public void onComplete(@Nullable Result result) {
105105
*
106106
* @param the JSON attribute key for the value to be updated
107107
* @param the value to be updated in the thermostat
108+
* @param the end point URI to use for the command
108109
* @return the JSON response string from the thermostat
109110
*/
110-
public String sendCommand(String cmdKey, @Nullable String cmdVal) {
111-
return sendCommand(cmdKey, cmdVal, null);
111+
public String sendCommand(String cmdKey, @Nullable String cmdVal, String resource) {
112+
return sendCommand(cmdKey, cmdVal, null, resource);
112113
}
113114

114115
/**
@@ -117,12 +118,14 @@ public String sendCommand(String cmdKey, @Nullable String cmdVal) {
117118
* @param the JSON attribute key for the value to be updated
118119
* @param the value to be updated in the thermostat
119120
* @param JSON string to send directly to the thermostat instead of a key/value pair
121+
* @param the end point URI to use for the command
120122
* @return the JSON response string from the thermostat
121123
*/
122-
public String sendCommand(@Nullable String cmdKey, @Nullable String cmdVal, @Nullable String cmdJson) {
124+
public String sendCommand(@Nullable String cmdKey, @Nullable String cmdVal, @Nullable String cmdJson,
125+
String resource) {
123126
// if we got a cmdJson string send that, otherwise build the json from the key and val params
124127
String postJson = cmdJson != null ? cmdJson : "{\"" + cmdKey + "\":" + cmdVal + "}";
125-
String urlStr = buildRequestURL(DEFAULT_RESOURCE);
128+
String urlStr = buildRequestURL(resource);
126129

127130
String output = "";
128131

bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/discovery/RadioThermostatDiscoveryService.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,12 @@ protected void startBackgroundDiscovery() {
8181
TimeUnit.SECONDS);
8282
}
8383

84-
@SuppressWarnings("null")
8584
@Override
8685
protected void stopBackgroundDiscovery() {
87-
if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
86+
ScheduledFuture<?> scheduledFuture = this.scheduledFuture;
87+
if (scheduledFuture != null) {
8888
scheduledFuture.cancel(true);
89+
this.scheduledFuture = null;
8990
}
9091
}
9192

bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/handler/RadioThermostatHandler.java

+30-19
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.openhab.core.library.types.PointType;
4747
import org.openhab.core.library.types.QuantityType;
4848
import org.openhab.core.library.types.StringType;
49+
import org.openhab.core.library.unit.ImperialUnits;
4950
import org.openhab.core.thing.Channel;
5051
import org.openhab.core.thing.ChannelUID;
5152
import org.openhab.core.thing.Thing;
@@ -216,7 +217,7 @@ public void dispose() {
216217
}
217218

218219
public void handleRawCommand(@Nullable String rawCommand) {
219-
connector.sendCommand(null, null, rawCommand);
220+
connector.sendCommand(null, null, rawCommand, DEFAULT_RESOURCE);
220221
}
221222

222223
@Override
@@ -226,21 +227,19 @@ public void handleCommand(ChannelUID channelUID, Command command) {
226227
} else {
227228
Integer cmdInt = -1;
228229
String cmdStr = command.toString();
229-
if (cmdStr != null) {
230-
try {
231-
// parse out an Integer from the string
232-
// ie '70.5 F' becomes 70, also handles negative numbers
233-
cmdInt = NumberFormat.getInstance().parse(cmdStr).intValue();
234-
} catch (ParseException e) {
235-
logger.debug("Command: {} -> Not an integer", cmdStr);
236-
}
230+
try {
231+
// parse out an Integer from the string
232+
// ie '70.5 F' becomes 70, also handles negative numbers
233+
cmdInt = NumberFormat.getInstance().parse(cmdStr).intValue();
234+
} catch (ParseException e) {
235+
logger.debug("Command: {} -> Not an integer", cmdStr);
237236
}
238237

239238
switch (channelUID.getId()) {
240239
case MODE:
241240
// only do if commanded mode is different than current mode
242241
if (!cmdInt.equals(rthermData.getThermostatData().getMode())) {
243-
connector.sendCommand("tmode", cmdStr);
242+
connector.sendCommand("tmode", cmdStr, DEFAULT_RESOURCE);
244243

245244
// set the new operating mode, reset everything else,
246245
// because refreshing the tstat data below is really slow.
@@ -253,26 +252,26 @@ public void handleCommand(ChannelUID channelUID, Command command) {
253252
rthermData.getThermostatData().setProgramMode(-1);
254253
updateChannel(PROGRAM_MODE, rthermData);
255254

256-
// now just trigger a refresh of the thermost to get the new active setpoint
255+
// now just trigger a refresh of the thermostat to get the new active setpoint
257256
// this takes a while for the JSON request to complete (async).
258257
connector.getAsyncThermostatData(DEFAULT_RESOURCE);
259258
}
260259
break;
261260
case FAN_MODE:
262261
rthermData.getThermostatData().setFanMode(cmdInt);
263-
connector.sendCommand("fmode", cmdStr);
262+
connector.sendCommand("fmode", cmdStr, DEFAULT_RESOURCE);
264263
break;
265264
case PROGRAM_MODE:
266265
rthermData.getThermostatData().setProgramMode(cmdInt);
267-
connector.sendCommand("program_mode", cmdStr);
266+
connector.sendCommand("program_mode", cmdStr, DEFAULT_RESOURCE);
268267
break;
269268
case HOLD:
270269
if (command instanceof OnOffType && command == OnOffType.ON) {
271270
rthermData.getThermostatData().setHold(1);
272-
connector.sendCommand("hold", "1");
271+
connector.sendCommand("hold", "1", DEFAULT_RESOURCE);
273272
} else if (command instanceof OnOffType && command == OnOffType.OFF) {
274273
rthermData.getThermostatData().setHold(0);
275-
connector.sendCommand("hold", "0");
274+
connector.sendCommand("hold", "0", DEFAULT_RESOURCE);
276275
}
277276
break;
278277
case SET_POINT:
@@ -287,7 +286,16 @@ public void handleCommand(ChannelUID channelUID, Command command) {
287286
// don't do anything if we are not in heat or cool mode
288287
break;
289288
}
290-
connector.sendCommand(cmdKey, cmdInt.toString());
289+
connector.sendCommand(cmdKey, cmdInt.toString(), DEFAULT_RESOURCE);
290+
break;
291+
case REMOTE_TEMP:
292+
if (cmdInt != -1) {
293+
QuantityType<?> remoteTemp = ((QuantityType<Temperature>) command)
294+
.toUnit(ImperialUnits.FAHRENHEIT);
295+
connector.sendCommand("rem_temp", String.valueOf(remoteTemp.intValue()), REMOTE_TEMP_RESOURCE);
296+
} else {
297+
connector.sendCommand("rem_mode", "0", REMOTE_TEMP_RESOURCE);
298+
}
291299
break;
292300
default:
293301
logger.warn("Unsupported command: {}", command.toString());
@@ -320,7 +328,10 @@ public void onNewMessageEvent(RadioThermostatEvent event) {
320328
updateAllChannels();
321329
break;
322330
case HUMIDITY_RESOURCE:
323-
rthermData.setHumidity(gson.fromJson(evtVal, RadioThermostatHumidityDTO.class).getHumidity());
331+
RadioThermostatHumidityDTO dto = gson.fromJson(evtVal, RadioThermostatHumidityDTO.class);
332+
if (dto != null) {
333+
rthermData.setHumidity(dto.getHumidity());
334+
}
324335
updateChannel(HUMIDITY, rthermData);
325336
break;
326337
case RUNTIME_RESOURCE:
@@ -382,7 +393,7 @@ private void updateChannel(String channelId, RadioThermostatDTO rthermData) {
382393

383394
/**
384395
* Update a given channelId from the thermostat data
385-
*
396+
*
386397
* @param the channel id to be updated
387398
* @param data the RadioThermostat dto
388399
* @return the value to be set in the state
@@ -456,7 +467,7 @@ private void updateAllChannels() {
456467

457468
/**
458469
* Build a list of fan modes based on what model thermostat is used
459-
*
470+
*
460471
* @return list of state options for thermostat fan modes
461472
*/
462473
private List<StateOption> getFanModeOptions() {

bundles/org.openhab.binding.radiothermostat/src/main/resources/OH-INF/thing/thing-types.xml

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<channel id="hold" typeId="hold"/>
2323
<channel id="status" typeId="status"/>
2424
<channel id="fan_status" typeId="fan_status"/>
25+
<channel id="remote_temp" typeId="remote_temp"/>
2526
<channel id="day" typeId="t_day"/>
2627
<channel id="hour" typeId="t_hour"/>
2728
<channel id="minute" typeId="t_minute"/>
@@ -157,6 +158,14 @@
157158
<state min="0" max="2" pattern="%d"/>
158159
</channel-type>
159160

161+
<channel-type id="remote_temp" advanced="true">
162+
<item-type>Number:Temperature</item-type>
163+
<label>Remote Temperature</label>
164+
<description>The remote temperature takes the place of the ambient temperature as read by the local thermostat
165+
temperature sensor</description>
166+
<state pattern="%d %unit%"/>
167+
</channel-type>
168+
160169
<channel-type id="t_day" advanced="true">
161170
<item-type>Number</item-type>
162171
<label>Day</label>

0 commit comments

Comments
 (0)