[radiothermostat] Add message display channel and improve ThingActions (#14799)

* Add price message channel

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
This commit is contained in:
mlobstein 2023-04-15 14:20:20 -05:00 committed by GitHub
parent ec30333314
commit 2c006ccd31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 142 additions and 65 deletions

View File

@ -88,6 +88,7 @@ The thermostat information that is retrieved is available as these channels:
| today_cool_runtime | Number:Time | The total number of minutes of cooling 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_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 | | yesterday_cool_runtime | Number:Time | The total number of minutes of cooling run-time yesterday |
| message | String (Write Only) | Used to display a number in the upper left 'price message' area of the thermostat's screen where the time is normally displayed |
## Full Example ## Full Example
@ -158,15 +159,16 @@ Number Therm_FanStatus "Fan Status [MAP(radiotherm.map):%s_fstus]"
Number Therm_Override "Override [MAP(radiotherm.map):%s_over]" { channel="radiothermostat:rtherm:mytherm1:override" } Number Therm_Override "Override [MAP(radiotherm.map):%s_over]" { channel="radiothermostat:rtherm:mytherm1:override" }
Switch Therm_Hold "Hold" { channel="radiothermostat:rtherm:mytherm1:hold" } Switch Therm_Hold "Hold" { channel="radiothermostat:rtherm:mytherm1:hold" }
Number Therm_Day "Thermostat Day [%s]" { channel="radiothermostat:rtherm:mytherm1:day" } Number Therm_Day "Thermostat Day [%d]" { channel="radiothermostat:rtherm:mytherm1:day" }
Number Therm_Hour "Thermostat Hour [%s]" { channel="radiothermostat:rtherm:mytherm1:hour" } Number Therm_Hour "Thermostat Hour [%d]" { channel="radiothermostat:rtherm:mytherm1:hour" }
Number Therm_Minute "Thermostat Minute [%s]" { channel="radiothermostat:rtherm:mytherm1:minute" } Number Therm_Minute "Thermostat Minute [%d]" { channel="radiothermostat:rtherm:mytherm1:minute" }
String Therm_Dstmp "Thermostat DateStamp [%s]" <time> { channel="radiothermostat:rtherm:mytherm1:dt_stamp" } String Therm_Dstmp "Thermostat DateStamp [%s]" <time> { channel="radiothermostat:rtherm:mytherm1:dt_stamp" }
Number:Time Therm_todayheat "Today's Heating Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:today_heat_runtime" } Number:Time Therm_todayheat "Today's Heating Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:today_heat_runtime" }
Number:Time Therm_todaycool "Today's Cooling Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:today_cool_runtime" } Number:Time Therm_todaycool "Today's Cooling Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:today_cool_runtime" }
Number:Time Therm_yesterdayheat "Yesterday's Heating Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:yesterday_heat_runtime" } 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" } Number:Time Therm_yesterdaycool "Yesterday's Cooling Runtime [%d %unit%]" { channel="radiothermostat:rtherm:mytherm1:yesterday_cool_runtime" }
String Therm_Message "Message: [%s]" { channel="radiothermostat:rtherm:mytherm1:message" }
// Override the thermostat's temperature reading with a value from an external sensor, set to -1 to revert to internal temperature mode // 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" } Number:Temperature Therm_Rtemp "Remote Temperature [%d]" <temperature> { channel="radiothermostat:rtherm:mytherm1:remote_temp" }
@ -228,5 +230,30 @@ then
// JSON to send directly to the thermostat's '/tstat' endpoint // JSON to send directly to the thermostat's '/tstat' endpoint
// See RadioThermostat_CT50_Honeywell_Wifi_API_V1.3.pdf for more detail // See RadioThermostat_CT50_Honeywell_Wifi_API_V1.3.pdf for more detail
actions.sendRawCommand('{"hold":1, "t_heat":' + "68" + ', "tmode":1}') actions.sendRawCommand('{"hold":1, "t_heat":' + "68" + ', "tmode":1}')
// Also a command can be sent to a specific endpoint on the thermostat by
// specifying it as the second argument to sendRawCommand():
// Reboot the thermostat
// actions.sendRawCommand('{"command": "reboot"}', 'sys/command')
// Control the energy LED (CT80 only) [0 = off, 1 = green, 2 = yellow, 4 = red]
// actions.sendRawCommand('{"energy_led": 1}', 'tstat/led')
// Send a message to the User Message Area (CT80 only)
// actions.sendRawCommand('{"line": 0, "message": "Hello World!"}', 'tstat/uma')
end
rule "Display outside temp in thermostat message area"
when
// An item containing the current outside temperature
Item OutsideTemp changed
then
// Display up to 5 numbers in the thermostat's Price Message Area (PMA)
// A decimal point can be used. CT80 can display a negative '-' number
// Send null or empty string to clear the number and restore the time display
var Number temp = Math.round((OutsideTemp.state as DecimalType).doubleValue).intValue
Therm_Message.sendCommand(temp)
end end
``` ```

View File

@ -14,8 +14,6 @@ package org.openhab.binding.radiothermostat.internal;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.measure.Unit; import javax.measure.Unit;
import javax.measure.quantity.Dimensionless; import javax.measure.quantity.Dimensionless;
@ -41,6 +39,8 @@ public class RadioThermostatBindingConstants {
public static final String PROPERTY_IP = "hostName"; public static final String PROPERTY_IP = "hostName";
public static final String PROPERTY_ISCT80 = "isCT80"; public static final String PROPERTY_ISCT80 = "isCT80";
public static final String JSON_TIME = "{\"day\":%s,\"hour\":%s,\"minute\":%s}"; public static final String JSON_TIME = "{\"day\":%s,\"hour\":%s,\"minute\":%s}";
public static final String JSON_PMA = "{\"line\":1,\"message\":\"%s\"}";
public static final String BLANK = "";
public static final String KEY_ERROR = "error"; public static final String KEY_ERROR = "error";
@ -52,6 +52,7 @@ public class RadioThermostatBindingConstants {
public static final String TIME_RESOURCE = "tstat/time"; public static final String TIME_RESOURCE = "tstat/time";
public static final String HEAT_PROGRAM_RESOURCE = "tstat/program/heat"; public static final String HEAT_PROGRAM_RESOURCE = "tstat/program/heat";
public static final String COOL_PROGRAM_RESOURCE = "tstat/program/cool"; public static final String COOL_PROGRAM_RESOURCE = "tstat/program/cool";
public static final String PMA_RESOURCE = "tstat/pma";
// List of all Thing Type UIDs // List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_RTHERM = new ThingTypeUID(BINDING_ID, "rtherm"); public static final ThingTypeUID THING_TYPE_RTHERM = new ThingTypeUID(BINDING_ID, "rtherm");
@ -76,12 +77,15 @@ public class RadioThermostatBindingConstants {
public static final String YESTERDAY_HEAT_RUNTIME = "yesterday_heat_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 YESTERDAY_COOL_RUNTIME = "yesterday_cool_runtime";
public static final String REMOTE_TEMP = "remote_temp"; public static final String REMOTE_TEMP = "remote_temp";
public static final String MESSAGE = "message";
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_RTHERM); 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, public static final Set<String> SUPPORTED_CHANNEL_IDS = Set.of(TEMPERATURE, HUMIDITY, MODE, FAN_MODE, PROGRAM_MODE,
TODAY_HEAT_RUNTIME, TODAY_COOL_RUNTIME, YESTERDAY_HEAT_RUNTIME, YESTERDAY_COOL_RUNTIME, REMOTE_TEMP) SET_POINT, OVERRIDE, HOLD, STATUS, FAN_STATUS, DAY, HOUR, MINUTE, DATE_STAMP, TODAY_HEAT_RUNTIME,
.collect(Collectors.toSet()); TODAY_COOL_RUNTIME, YESTERDAY_HEAT_RUNTIME, YESTERDAY_COOL_RUNTIME, REMOTE_TEMP, MESSAGE);
public static final Set<String> NO_UPDATE_CHANNEL_IDS = Set.of(REMOTE_TEMP, MESSAGE);
// Units of measurement of the data delivered by the API // Units of measurement of the data delivered by the API
public static final Unit<Temperature> API_TEMPERATURE_UNIT = ImperialUnits.FAHRENHEIT; public static final Unit<Temperature> API_TEMPERATURE_UNIT = ImperialUnits.FAHRENHEIT;

View File

@ -35,7 +35,7 @@ public class RadioThermostatThingActions implements ThingActions {
private @Nullable RadioThermostatHandler handler; private @Nullable RadioThermostatHandler handler;
@RuleAction(label = "send a raw command", description = "Send a raw command to the thermostat.") @RuleAction(label = "send a raw command", description = "Send a raw command to the thermostat's 'tstat' endpoint.")
public void sendRawCommand(@ActionInput(name = "sendRawCommand") @Nullable String rawCommand) { public void sendRawCommand(@ActionInput(name = "sendRawCommand") @Nullable String rawCommand) {
if (rawCommand == null) { if (rawCommand == null) {
logger.warn("sendRawCommand called with null command, ignoring"); logger.warn("sendRawCommand called with null command, ignoring");
@ -49,11 +49,30 @@ public class RadioThermostatThingActions implements ThingActions {
} }
} }
/** Static alias to support the old DSL rules engine and make the action available there. */ @RuleAction(label = "send a raw command", description = "Send a raw command to a specific endpoint on the thermostat.")
public void sendRawCommand(@ActionInput(name = "sendRawCommand") @Nullable String rawCommand,
@Nullable String resource) {
if (rawCommand == null || resource == null) {
logger.warn("sendRawCommand called with null command, ignoring");
return;
}
RadioThermostatHandler localHandler = handler;
if (localHandler != null) {
localHandler.handleRawCommand(rawCommand, resource);
logger.debug("sendRawCommand called with raw command: {}, resource: {}", rawCommand, resource);
}
}
/** Static aliases to support the old DSL rules engine and make the action available there. */
public static void sendRawCommand(ThingActions actions, @Nullable String rawCommand) { public static void sendRawCommand(ThingActions actions, @Nullable String rawCommand) {
((RadioThermostatThingActions) actions).sendRawCommand(rawCommand); ((RadioThermostatThingActions) actions).sendRawCommand(rawCommand);
} }
public static void sendRawCommand(ThingActions actions, @Nullable String rawCommand, @Nullable String resource) {
((RadioThermostatThingActions) actions).sendRawCommand(rawCommand, resource);
}
@Override @Override
public void setThingHandler(@Nullable ThingHandler handler) { public void setThingHandler(@Nullable ThingHandler handler) {
this.handler = (RadioThermostatHandler) handler; this.handler = (RadioThermostatHandler) handler;

View File

@ -44,18 +44,18 @@ import org.slf4j.LoggerFactory;
public class RadioThermostatConnector { public class RadioThermostatConnector {
private final Logger logger = LoggerFactory.getLogger(RadioThermostatConnector.class); private final Logger logger = LoggerFactory.getLogger(RadioThermostatConnector.class);
private static final String URL = "http://%hostName%/%resource%"; private static final String URL = "http://%s/%s";
private final HttpClient httpClient; private final HttpClient httpClient;
private final List<RadioThermostatEventListener> listeners = new CopyOnWriteArrayList<>(); private final List<RadioThermostatEventListener> listeners = new CopyOnWriteArrayList<>();
private @Nullable String hostName; private String hostName = BLANK;
public RadioThermostatConnector(HttpClient httpClient) { public RadioThermostatConnector(HttpClient httpClient) {
this.httpClient = httpClient; this.httpClient = httpClient;
} }
public void setThermostatHostName(@Nullable String hostName) { public void setThermostatHostName(String hostName) {
this.hostName = hostName; this.hostName = hostName;
} }
@ -84,16 +84,14 @@ public class RadioThermostatConnector {
* @param resouce the url of the json resource on the thermostat * @param resouce the url of the json resource on the thermostat
*/ */
public void getAsyncThermostatData(String resource) { public void getAsyncThermostatData(String resource) {
String urlStr = buildRequestURL(resource); httpClient.newRequest(buildRequestURL(resource)).method(GET).timeout(30, TimeUnit.SECONDS)
.send(new BufferingResponseListener() {
httpClient.newRequest(urlStr).method(GET).timeout(30, TimeUnit.SECONDS).send(new BufferingResponseListener() {
@Override @Override
public void onComplete(@Nullable Result result) { public void onComplete(@Nullable Result result) {
if (result != null && !result.isFailed()) { if (result != null && !result.isFailed()) {
String response = getContentAsString(); dispatchKeyValue(resource, getContentAsString());
dispatchKeyValue(resource, response);
} else { } else {
dispatchKeyValue(KEY_ERROR, ""); dispatchKeyValue(KEY_ERROR, BLANK);
} }
} }
}); });
@ -124,30 +122,27 @@ public class RadioThermostatConnector {
String resource) { String resource) {
// if we got a cmdJson string send that, otherwise build the json from the key and val params // 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 postJson = cmdJson != null ? cmdJson : "{\"" + cmdKey + "\":" + cmdVal + "}";
String urlStr = buildRequestURL(resource);
String output = "";
try { try {
Request request = httpClient.POST(urlStr); Request request = httpClient.POST(buildRequestURL(resource));
request.header(HttpHeader.ACCEPT, "text/plain"); request.header(HttpHeader.ACCEPT, "text/plain");
request.header(HttpHeader.CONTENT_TYPE, "text/plain"); request.header(HttpHeader.CONTENT_TYPE, "text/plain");
request.content(new StringContentProvider(postJson), "application/json"); request.content(new StringContentProvider(postJson), "application/json");
logger.trace("Sending POST request to '{}', data: {}", resource, postJson); logger.trace("Sending POST request to '{}', data: {}", resource, postJson);
ContentResponse contentResponse = request.send(); ContentResponse contentResponse = request.send();
int httpStatus = contentResponse.getStatus();
if (httpStatus != OK_200) { if (contentResponse.getStatus() != OK_200) {
throw new RadioThermostatHttpException("Thermostat HTTP response code was: " + httpStatus); throw new RadioThermostatHttpException(
"Thermostat HTTP response code was: " + contentResponse.getStatus());
} }
output = contentResponse.getContentAsString();
logger.trace("Response: {}", output); logger.trace("Response: {}", contentResponse.getContentAsString());
return contentResponse.getContentAsString();
} catch (RadioThermostatHttpException | InterruptedException | TimeoutException | ExecutionException e) { } catch (RadioThermostatHttpException | InterruptedException | TimeoutException | ExecutionException e) {
logger.debug("Error executing thermostat command: {}, {}", postJson, e.getMessage()); logger.debug("Error executing thermostat command: {}, {}", postJson, e.getMessage());
return BLANK;
} }
return output;
} }
/** /**
@ -156,14 +151,7 @@ public class RadioThermostatConnector {
* @return a valid URL for the thermostat's JSON interface * @return a valid URL for the thermostat's JSON interface
*/ */
private String buildRequestURL(String resource) { private String buildRequestURL(String resource) {
String hostName = this.hostName; return String.format(URL, hostName, resource);
if (hostName == null) {
throw new IllegalStateException("hostname must not be null");
}
String urlStr = URL.replace("%hostName%", hostName);
urlStr = urlStr.replace("%resource%", resource);
return urlStr;
} }
/** /**

View File

@ -14,7 +14,6 @@ package org.openhab.binding.radiothermostat.internal.handler;
import static org.openhab.binding.radiothermostat.internal.RadioThermostatBindingConstants.*; import static org.openhab.binding.radiothermostat.internal.RadioThermostatBindingConstants.*;
import java.math.BigDecimal;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.text.ParseException; import java.text.ParseException;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
@ -96,8 +95,8 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
private boolean disableLogs = false; private boolean disableLogs = false;
private boolean clockSync = false; private boolean clockSync = false;
private String setpointCmdKeyPrefix = "t_"; private String setpointCmdKeyPrefix = "t_";
private String heatProgramJson = ""; private String heatProgramJson = BLANK;
private String coolProgramJson = ""; private String coolProgramJson = BLANK;
public RadioThermostatHandler(Thing thing, RadioThermostatStateDescriptionProvider stateDescriptionProvider, public RadioThermostatHandler(Thing thing, RadioThermostatStateDescriptionProvider stateDescriptionProvider,
HttpClient httpClient) { HttpClient httpClient) {
@ -119,7 +118,7 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
this.disableLogs = config.disableLogs; this.disableLogs = config.disableLogs;
this.clockSync = config.clockSync; this.clockSync = config.clockSync;
if (hostName == null || "".equals(hostName)) { if (hostName == null || hostName.isBlank()) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"@text/offline.configuration-error-hostname"); "@text/offline.configuration-error-hostname");
return; return;
@ -198,17 +197,17 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
Runnable runnable = () -> { Runnable runnable = () -> {
// populate the heat and cool programs on the thermostat from the user configuration, // populate the heat and cool programs on the thermostat from the user configuration,
// the commands will be sent each time the refresh job runs until a success response is seen // the commands will be sent each time the refresh job runs until a success response is seen
if (!"".equals(heatProgramJson)) { if (!heatProgramJson.isEmpty()) {
final String response = connector.sendCommand(null, null, heatProgramJson, HEAT_PROGRAM_RESOURCE); final String response = connector.sendCommand(null, null, heatProgramJson, HEAT_PROGRAM_RESOURCE);
if (response.contains("success")) { if (response.contains("success")) {
heatProgramJson = ""; heatProgramJson = BLANK;
} }
} }
if (!"".equals(coolProgramJson)) { if (!coolProgramJson.isEmpty()) {
final String response = connector.sendCommand(null, null, coolProgramJson, COOL_PROGRAM_RESOURCE); final String response = connector.sendCommand(null, null, coolProgramJson, COOL_PROGRAM_RESOURCE);
if (response.contains("success")) { if (response.contains("success")) {
coolProgramJson = ""; coolProgramJson = BLANK;
} }
} }
@ -307,6 +306,10 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
connector.sendCommand(null, null, rawCommand, DEFAULT_RESOURCE); connector.sendCommand(null, null, rawCommand, DEFAULT_RESOURCE);
} }
public void handleRawCommand(@Nullable String rawCommand, String resource) {
connector.sendCommand(null, null, rawCommand, resource);
}
@Override @Override
public void handleCommand(ChannelUID channelUID, Command command) { public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) { if (command instanceof RefreshType) {
@ -384,6 +387,13 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
connector.sendCommand("rem_mode", "0", REMOTE_TEMP_RESOURCE); connector.sendCommand("rem_mode", "0", REMOTE_TEMP_RESOURCE);
} }
break; break;
case MESSAGE:
if (!cmdStr.isEmpty()) {
connector.sendCommand(null, null, String.format(JSON_PMA, cmdStr), PMA_RESOURCE);
} else {
connector.sendCommand("mode", "0", PMA_RESOURCE);
}
break;
default: default:
logger.warn("Unsupported command: {}", command.toString()); logger.warn("Unsupported command: {}", command.toString());
} }
@ -460,10 +470,8 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
state = new DateTimeType((ZonedDateTime) value); state = new DateTimeType((ZonedDateTime) value);
} else if (value instanceof QuantityType<?>) { } else if (value instanceof QuantityType<?>) {
state = (QuantityType<?>) value; state = (QuantityType<?>) value;
} else if (value instanceof BigDecimal) { } else if (value instanceof Number) {
state = new DecimalType((BigDecimal) value); state = new DecimalType((Number) value);
} else if (value instanceof Integer) {
state = new DecimalType(BigDecimal.valueOf(((Integer) value).longValue()));
} else if (value instanceof String) { } else if (value instanceof String) {
state = new StringType(value.toString()); state = new StringType(value.toString());
} else if (value instanceof OnOffType) { } else if (value instanceof OnOffType) {
@ -556,9 +564,11 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
*/ */
private void updateAllChannels() { private void updateAllChannels() {
// Update all channels from rthermData // Update all channels from rthermData
for (Channel channel : getThing().getChannels()) { getThing().getChannels().forEach(channel -> {
if (!NO_UPDATE_CHANNEL_IDS.contains(channel.getUID().getId())) {
updateChannel(channel.getUID().getId(), rthermData); updateChannel(channel.getUID().getId(), rthermData);
} }
});
} }
/** /**
@ -569,11 +579,11 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
private List<StateOption> getFanModeOptions() { private List<StateOption> getFanModeOptions() {
List<StateOption> fanModeOptions = new ArrayList<>(); List<StateOption> fanModeOptions = new ArrayList<>();
fanModeOptions.add(new StateOption("0", "Auto")); fanModeOptions.add(new StateOption("0", "@text/options.fan-option-auto"));
if (this.isCT80) { if (this.isCT80) {
fanModeOptions.add(new StateOption("1", "Auto/Circulate")); fanModeOptions.add(new StateOption("1", "@text/options.fan-option-circulate"));
} }
fanModeOptions.add(new StateOption("2", "On")); fanModeOptions.add(new StateOption("2", "@text/options.fan-option-on"));
return fanModeOptions; return fanModeOptions;
} }

View File

@ -267,6 +267,8 @@ channel-type.radiothermostat.hold.label = Hold
channel-type.radiothermostat.hold.description = Indicates If the Current Set Point Temperature Is to Be Held Indefinitely channel-type.radiothermostat.hold.description = Indicates If the Current Set Point Temperature Is to Be Held Indefinitely
channel-type.radiothermostat.humidity.label = Humidity channel-type.radiothermostat.humidity.label = Humidity
channel-type.radiothermostat.humidity.description = The Current Humidity Reading of the Thermostat channel-type.radiothermostat.humidity.description = The Current Humidity Reading of the Thermostat
channel-type.radiothermostat.message.label = Message
channel-type.radiothermostat.message.description = Use this channel to display a number in the price message area
channel-type.radiothermostat.mode.label = Mode channel-type.radiothermostat.mode.label = Mode
channel-type.radiothermostat.mode.description = The Current Operating Mode of the HVAC System channel-type.radiothermostat.mode.description = The Current Operating Mode of the HVAC System
channel-type.radiothermostat.mode.state.option.0 = Off channel-type.radiothermostat.mode.state.option.0 = Off
@ -311,3 +313,6 @@ offline.configuration-error-hostname = Thermostat hostname must be specified
offline.configuration-error-heating-program = Thermostat HEATING program schedule is invalid, check configuration! offline.configuration-error-heating-program = Thermostat HEATING program schedule is invalid, check configuration!
offline.configuration-error-cooling-program = Thermostat COOLING program schedule is invalid, check configuration! offline.configuration-error-cooling-program = Thermostat COOLING program schedule is invalid, check configuration!
offline.communication-error-get-data = Error retrieving data from Thermostat offline.communication-error-get-data = Error retrieving data from Thermostat
options.fan-option-auto = Auto
options.fan-option-circulate = Auto/Circulate
options.fan-option-on = On

View File

@ -31,10 +31,14 @@
<channel id="today_cool_runtime" typeId="today_cool_runtime"/> <channel id="today_cool_runtime" typeId="today_cool_runtime"/>
<channel id="yesterday_heat_runtime" typeId="yesterday_heat_runtime"/> <channel id="yesterday_heat_runtime" typeId="yesterday_heat_runtime"/>
<channel id="yesterday_cool_runtime" typeId="yesterday_cool_runtime"/> <channel id="yesterday_cool_runtime" typeId="yesterday_cool_runtime"/>
<channel id="message" typeId="message"/>
</channels> </channels>
<config-description-ref uri="thing-type:radiothermostat:thermostatconfig"/> <properties>
<property name="thingTypeVersion">1</property>
</properties>
<config-description-ref uri="thing-type:radiothermostat:thermostatconfig"/>
</thing-type> </thing-type>
<channel-type id="temp-temperature"> <channel-type id="temp-temperature">
@ -187,4 +191,10 @@
<state readOnly="true" pattern="%d %unit%"/> <state readOnly="true" pattern="%d %unit%"/>
</channel-type> </channel-type>
<channel-type id="message" advanced="true">
<item-type>String</item-type>
<label>Message</label>
<description>Use this channel to display a number in the price message area</description>
</channel-type>
</thing:thing-descriptions> </thing:thing-descriptions>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
<thing-type uid="radiothermostat:rtherm">
<instruction-set targetVersion="1">
<add-channel id="message">
<type>radiothermostat:message</type>
</add-channel>
</instruction-set>
</thing-type>
</update:update-descriptions>