[openthermgateway] Fix for #9205 incorrect control setpoint override (#9206)

* Initial attempt to resolve issue with flickering statuses when override
present on OTGW
* Update Units

Signed-off-by: James Melville <jamesmelville@gmail.com>
This commit is contained in:
James Melville 2020-12-08 01:03:40 +00:00 committed by GitHub
parent e19c16565d
commit 20e03c257a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 259 additions and 121 deletions

View File

@ -32,36 +32,40 @@ The configuration settings for the thing are Hostname/IP address and Port, which
The OpenTherm Gateway binding supports the following channels:
| Channel Type ID | Item Type | Description | Read Only |
|----------------------|-----------|----------------------------------------------------------|-----------|
| roomtemp | Number | Current sensed room temperature | yes |
| roomsetpoint | Number | Current room temperature setpoint | yes |
| temperaturetemporary | Number | Temporary override room temperature setpoint | no |
| temperatureconstant | Number | Constant override room temperature setpoint | no |
| controlsetpoint | Number | Central heating water setpoint | yes |
| dhwtemp | Number | Domestic hot water temperature | yes |
| tdhwset | Number | Domestic hot water temperature setpoint | yes |
| overridedhwsetpoint | Number | Domestic hot water temperature setpoint override | no |
| flowtemp | Number | Boiler water temperature | yes |
| returntemp | Number | Return water temperature | yes |
| outsidetemp | Number | Outside temperature | no |
| waterpressure | Number | Central heating water pressure | yes |
| ch_enable | Switch | Central heating enabled | yes |
| ch_mode | Switch | Central heating active | yes |
| dhw_enable | Switch | Domestic hot water enabled | yes |
| dhw_mode | Switch | Domestic hot water active | yes |
| flame | Switch | Burner active | yes |
| modulevel | Number | Relative modulation level | yes |
| maxrelmdulevel | Number | Maximum relative modulation level | yes |
| fault | Switch | Fault indication | yes |
| servicerequest | Switch | Service required | yes |
| lockout-reset | Switch | Lockout-reset enabled | yes |
| lowwaterpress | Switch | Low water pressure fault | yes |
| gasflamefault | Switch | Gas or flame fault | yes |
| airpressfault | Switch | Air pressure fault | yes |
| waterovtemp | Switch | Water over-temperature fault | yes |
| oemfaultcode | Switch | OEM fault code | yes |
| sendcommand | Text | Channel to send commands to the OpenTherm Gateway device | no |
| Channel Type ID | Item Type | Description | Read Only |
|--------------------------|----------------------|----------------------------------------------------------|-----------|
| roomtemp | Number:Temperature | Current sensed room temperature | yes |
| roomsetpoint | Number:Temperature | Current room temperature setpoint | yes |
| temperaturetemporary | Number:Temperature | Temporary override room temperature setpoint | no |
| temperatureconstant | Number:Temperature | Constant override room temperature setpoint | no |
| controlsetpoint | Number:Temperature | Central heating water setpoint set at boiler | yes |
| controlsetpointrequested | Number:Temperature | Central heating water setpoint requested by thermostat | yes |
| controlsetpointoverride | Number:Temperature | Central heating water setpoint configured at gateway | no |
| dhwtemp | Number:Temperature | Domestic hot water temperature | yes |
| tdhwset | Number:Temperature | Domestic hot water temperature setpoint | yes |
| overridedhwsetpoint | Number:Temperature | Domestic hot water temperature setpoint override | no |
| flowtemp | Number:Temperature | Boiler water temperature | yes |
| returntemp | Number:Temperature | Return water temperature | yes |
| outsidetemp | Number:Temperature | Outside temperature | no |
| waterpressure | Number:Pressure | Central heating water pressure | yes |
| ch_enable | Switch | Central heating enabled set at boiler | yes |
| ch_enablerequested | Switch | Central heating enabled requested by thermostat | yes |
| ch_enableoverride | Switch | Central heating enabled overridden at gateway | yes |
| ch_mode | Switch | Central heating active | yes |
| dhw_enable | Switch | Domestic hot water enabled | yes |
| dhw_mode | Switch | Domestic hot water active | yes |
| flame | Switch | Burner active | yes |
| modulevel | Number:Dimensionless | Relative modulation level | yes |
| maxrelmdulevel | Number:Dimensionless | Maximum relative modulation level | yes |
| fault | Switch | Fault indication | yes |
| servicerequest | Switch | Service required | yes |
| lockout-reset | Switch | Lockout-reset enabled | yes |
| lowwaterpress | Switch | Low water pressure fault | yes |
| gasflamefault | Switch | Gas or flame fault | yes |
| airpressfault | Switch | Air pressure fault | yes |
| waterovtemp | Switch | Water over-temperature fault | yes |
| oemfaultcode | Switch | OEM fault code | yes |
| sendcommand | Text | Channel to send commands to the OpenTherm Gateway device | no |
## Full Example
@ -74,25 +78,29 @@ Thing openthermgateway:otgw:1 [ ipaddress="192.168.1.100", port=8000, connection
### demo.items
```
Number RoomTemperature "Room temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:roomtemp" }
Number RoomSetpoint "Room setpoint [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:roomsetpoint" }
Number TemporaryRoomSetpointOverride "Temporary room setpoint override [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:temperaturetemporary" }
Number ConstantRoomSetpointOverride "Constant room setpoint override [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:temperatureconstant" }
Number ControlSetpoint "Control setpoint [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:controlsetpoint" }
Number DomesticHotWaterTemperature "Domestic hot water temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:dhwtemp" }
Number DomesticHotWaterSetpoint "Domestic hot water setpoint [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:tdhwset" }
Number DomesticHotWaterSetpointOverride "Domestic hot water setpoint override [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:overridedhwsetpoint" }
Number BoilerWaterTemperature "Boiler water temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:flowtemp" }
Number ReturnWaterTemperature "Return water temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:returntemp" }
Number OutsideTemperature "Outside temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:outsidetemp" }
Number CentralHeatingWaterPressure "Central heating water pressure [%.1f bar]" { channel="openthermgateway:otgw:1:waterpressure" }
Number:Temperature RoomTemperature "Room temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:roomtemp" }
Number:Temperature RoomSetpoint "Room setpoint [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:roomsetpoint" }
Number:Temperature TemporaryRoomSetpointOverride "Temporary room setpoint override [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:temperaturetemporary" }
Number:Temperature ConstantRoomSetpointOverride "Constant room setpoint override [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:temperatureconstant" }
Number:Temperature ControlSetpoint "Control setpoint [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:controlsetpoint" }
Number:Temperature ControlSetpointRequested "Control setpoint requested [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:controlsetpointrequested" }
Number:Temperature ControlSetpointOverride "Control setpoint override [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:controlsetpointoverride" }
Number:Temperature DomesticHotWaterTemperature "Domestic hot water temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:dhwtemp" }
Number:Temperature DomesticHotWaterSetpoint "Domestic hot water setpoint [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:tdhwset" }
Number:Temperature DomesticHotWaterSetpointOverride "Domestic hot water setpoint override [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:overridedhwsetpoint" }
Number:Temperature BoilerWaterTemperature "Boiler water temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:flowtemp" }
Number:Temperature ReturnWaterTemperature "Return water temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:returntemp" }
Number:Temperature OutsideTemperature "Outside temperature [%.1f °C]" <temperature> { channel="openthermgateway:otgw:1:outsidetemp" }
Number:Pressure CentralHeatingWaterPressure "Central heating water pressure [%.1f bar]" { channel="openthermgateway:otgw:1:waterpressure" }
Switch CentralHeatingEnabled "Central heating enabled" <switch> { channel="openthermgateway:otgw:1:ch_enable" }
Switch CentralHeatingEnabledRequested "Central heating enabled requested" <switch> { channel="openthermgateway:otgw:1:ch_enablerequested" }
Switch CentralHeatingEnabledOverride "Central heating enabled override" <switch> { channel="openthermgateway:otgw:1:ch_enableoverride" }
Switch CentralHeatingActive "Central heating active" <switch> { channel="openthermgateway:otgw:1:ch_mode" }
Switch DomesticHotWaterEnabled "Domestic hot water enabled" <switch> { channel="openthermgateway:otgw:1:dhw_enable" }
Switch DomesticHotWaterActive "Domestic hot water active" <switch> { channel="openthermgateway:otgw:1:dhw_mode" }
Switch BurnerActive "Burner active" <switch> { channel="openthermgateway:otgw:1:flame" }
Number RelativeModulationLevel "Relative modulation level [%.1f %%]" { channel="openthermgateway:otgw:1:modulevel" }
Number MaximumRelativeModulationLevel "Maximum relative modulation level [%.1f %%]" { channel="openthermgateway:otgw:1:maxrelmdulevel" }
Number:Dimensionless RelativeModulationLevel "Relative modulation level [%.1f %%]" { channel="openthermgateway:otgw:1:modulevel" }
Number:Dimensionless MaximumRelativeModulationLevel "Maximum relative modulation level [%.1f %%]" { channel="openthermgateway:otgw:1:maxrelmdulevel" }
Switch Fault "Fault indication" <switch> { channel="openthermgateway:otgw:1:fault" }
Switch ServiceRequest "Service required" <switch> { channel="openthermgateway:otgw:1:servicerequest" }
Switch LockoutReset "Lockout-reset" <switch> { channel="openthermgateway:otgw:1:lockout-reset" }
@ -114,6 +122,8 @@ sitemap demo label="Main Menu" {
Setpoint item="TemporaryRoomSetpointOverride" icon="temperature" label="Temporary room setpoint override [%.1f °C]" minValue="0" maxValue="30" step="0.1"
Setpoint item="ConstantRoomSetpointOverride" icon="temperature" label="Constant room setpoint override [%.1f °C]" minValue="0" maxValue="30" step="0.1"
Text item="ControlSetpoint" icon="temperature" label="Control setpoint [%.1f °C]"
Text item="ControlSetpointRequested" icon="temperature" label="Control setpoint requested [%.1f °C]"
Setpoint item="ControlSetpointOverride" icon="temperature" label="Control setpoint override [%.1f °C]" minValue="0" maxValue="100" step="1"
Text item="DomesticHotWaterTemperature" icon="temperature" label="Domestic hot water temperature [%.1f °C]"
Text item="DomesticHotWaterSetpoint" icon="temperature" label="Domestic hot water setpoint [%.1f °C]"
Setpoint item="DomesticHotWaterSetpointOverride" icon="temperature" label="Domestic hot water setpoint override [%.1f °C]" minValue="0" maxValue="100" step="0.1"
@ -122,6 +132,8 @@ sitemap demo label="Main Menu" {
Setpoint item="OutsideTemperature" icon="temperature" label="Outside temperature [%.1f °C]" minValue="-40" maxValue="100" step="0.1"
Text item="CentralHeatingWaterPressure" icon="" label="Central heating water pressure [%.1f bar]"
Switch item="CentralHeatingEnabled" icon="switch" label="Central heating enabled"
Switch item="CentralHeatingEnabledRequested" icon="switch" label="Central heating enabled requested"
Switch item="CentralHeatingEnabledOverride" icon="switch" label="Central heating enabled override"
Switch item="CentralHeatingActive" icon="switch" label="Central heating active"
Switch item="DomesticHotWaterEnabled" icon="switch" label="Domestic hot water enabled"
Switch item="DomesticHotWaterActive" icon="switch" label="Domestic hot water active"

View File

@ -46,8 +46,12 @@ public class OpenThermGatewayBindingConstants {
public static final String CHANNEL_RETURN_TEMPERATURE = "returntemp";
public static final String CHANNEL_OUTSIDE_TEMPERATURE = "outsidetemp";
public static final String CHANNEL_CENTRAL_HEATING_WATER_SETPOINT = "controlsetpoint";
public static final String CHANNEL_REQUESTED_CENTRAL_HEATING_WATER_SETPOINT = "controlsetpointrequested";
public static final String CHANNEL_OVERRIDE_CENTRAL_HEATING_WATER_SETPOINT = "controlsetpointoverride";
public static final String CHANNEL_CENTRAL_HEATING_WATER_PRESSURE = "waterpressure";
public static final String CHANNEL_CENTRAL_HEATING_ENABLED = "ch_enable";
public static final String CHANNEL_REQUESTED_CENTRAL_HEATING_ENABLED = "ch_enablerequested";
public static final String CHANNEL_OVERRIDE_CENTRAL_HEATING_ENABLED = "ch_enableoverride";
public static final String CHANNEL_CENTRAL_HEATING_MODE = "ch_mode";
public static final String CHANNEL_DOMESTIC_HOT_WATER_TEMPERATURE = "dhwtemp";
public static final String CHANNEL_DOMESTIC_HOT_WATER_ENABLED = "dhw_enable";
@ -68,8 +72,10 @@ public class OpenThermGatewayBindingConstants {
public static final Set<String> SUPPORTED_CHANNEL_IDS = Collections
.unmodifiableSet(Stream.of(CHANNEL_ROOM_TEMPERATURE, CHANNEL_ROOM_SETPOINT, CHANNEL_FLOW_TEMPERATURE,
CHANNEL_RETURN_TEMPERATURE, CHANNEL_OUTSIDE_TEMPERATURE, CHANNEL_CENTRAL_HEATING_WATER_PRESSURE,
CHANNEL_CENTRAL_HEATING_ENABLED, CHANNEL_CENTRAL_HEATING_MODE,
CHANNEL_CENTRAL_HEATING_WATER_SETPOINT, CHANNEL_DOMESTIC_HOT_WATER_TEMPERATURE,
CHANNEL_CENTRAL_HEATING_ENABLED, CHANNEL_REQUESTED_CENTRAL_HEATING_ENABLED,
CHANNEL_OVERRIDE_CENTRAL_HEATING_ENABLED, CHANNEL_CENTRAL_HEATING_MODE,
CHANNEL_CENTRAL_HEATING_WATER_SETPOINT, CHANNEL_REQUESTED_CENTRAL_HEATING_WATER_SETPOINT,
CHANNEL_OVERRIDE_CENTRAL_HEATING_WATER_SETPOINT, CHANNEL_DOMESTIC_HOT_WATER_TEMPERATURE,
CHANNEL_DOMESTIC_HOT_WATER_ENABLED, CHANNEL_DOMESTIC_HOT_WATER_MODE,
CHANNEL_DOMESTIC_HOT_WATER_SETPOINT, CHANNEL_FLAME, CHANNEL_RELATIVE_MODULATION_LEVEL,
CHANNEL_MAXIMUM_MODULATION_LEVEL, CHANNEL_FAULT, CHANNEL_SERVICEREQUEST, CHANNEL_REMOTE_RESET,

View File

@ -40,6 +40,7 @@ import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -87,6 +88,10 @@ public class OpenThermGatewayHandler extends BaseThingHandler implements OpenThe
GatewayCommand gatewayCommand = null;
if (command instanceof OnOffType) {
OnOffType onOff = (OnOffType) command;
gatewayCommand = GatewayCommand.parse(code, onOff == OnOffType.ON ? "1" : "0");
}
if (command instanceof QuantityType<?>) {
QuantityType<?> quantityType = ((QuantityType<?>) command).toUnit(SIUnits.CELSIUS);
@ -106,6 +111,16 @@ public class OpenThermGatewayHandler extends BaseThingHandler implements OpenThe
if (conn != null) {
conn.sendCommand(gatewayCommand);
if (code == GatewayCommandCode.ControlSetpoint) {
if (gatewayCommand.getMessage().equals("0.0")) {
updateState(
OpenThermGatewayBindingConstants.CHANNEL_OVERRIDE_CENTRAL_HEATING_WATER_SETPOINT,
UnDefType.UNDEF);
}
updateState(OpenThermGatewayBindingConstants.CHANNEL_OVERRIDE_CENTRAL_HEATING_ENABLED,
OnOffType.from(!gatewayCommand.getMessage().equals("0.0")));
}
}
}
}
@ -153,7 +168,8 @@ public class OpenThermGatewayHandler extends BaseThingHandler implements OpenThe
for (DataItem dataItem : dataItems) {
String channelId = dataItem.getSubject();
if (!OpenThermGatewayBindingConstants.SUPPORTED_CHANNEL_IDS.contains(channelId)) {
if (!OpenThermGatewayBindingConstants.SUPPORTED_CHANNEL_IDS.contains(channelId)
|| (dataItem.getFilteredCode() != null && dataItem.getFilteredCode() != message.getCode())) {
continue;
}
@ -264,6 +280,10 @@ public class OpenThermGatewayHandler extends BaseThingHandler implements OpenThe
return GatewayCommandCode.TemperatureOutside;
case OpenThermGatewayBindingConstants.CHANNEL_OVERRIDE_DHW_SETPOINT:
return GatewayCommandCode.SetpointWater;
case OpenThermGatewayBindingConstants.CHANNEL_OVERRIDE_CENTRAL_HEATING_WATER_SETPOINT:
return GatewayCommandCode.ControlSetpoint;
case OpenThermGatewayBindingConstants.CHANNEL_OVERRIDE_CENTRAL_HEATING_ENABLED:
return GatewayCommandCode.CentralHeating;
case OpenThermGatewayBindingConstants.CHANNEL_SEND_COMMAND:
return null;
default:

View File

@ -0,0 +1,49 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openthermgateway.internal;
/**
* The {@link CodeType} field is not part of OpenTherm specification, but added by OpenTherm Gateway.
* It can be any of the following:
*
* T: Message received from the thermostat
* B: Message received from the boiler
* R: Request sent to the boiler
* A: Response returned to the thermostat
* E: Parity or stop bit error
*
* @author Arjen Korevaar - Initial contribution
* @author James Melville - Introduced code filtering functionality
*/
public enum CodeType {
/**
* Message received from the thermostat
*/
T,
/**
* Message received from the boiler
*/
B,
/**
* Request sent to the boiler from OTGW, only present if value modified by OTGW
*/
R,
/**
* Response returned to the thermostat from OTGW, only present if value modified by OTGW
*/
A,
/**
* Parity or stop bit error
*/
E
}

View File

@ -19,7 +19,7 @@ import org.eclipse.jdt.annotation.Nullable;
/**
* The {@link DataItem} holds the internal OpenTherm message and meta data.
*
*
* @author Arjen Korevaar - Initial contribution
*/
@NonNullByDefault
@ -31,6 +31,7 @@ public class DataItem {
private int bitpos;
private String subject;
private @Nullable Unit<?> unit;
private @Nullable CodeType filteredCode;
public int getID() {
return id;
@ -60,17 +61,32 @@ public class DataItem {
return unit;
}
public @Nullable CodeType getFilteredCode() {
return filteredCode;
}
public DataItem(int id, Msg msg, ByteType byteType, DataType dataType, int bit, String subject) {
this(id, msg, byteType, dataType, bit, subject, null, null);
}
public DataItem(int id, Msg msg, ByteType byteType, DataType dataType, int bit, String subject, Unit<?> unit) {
this(id, msg, byteType, dataType, bit, subject, unit, null);
}
public DataItem(int id, Msg msg, ByteType byteType, DataType dataType, int bit, String subject,
CodeType filteredCode) {
this(id, msg, byteType, dataType, bit, subject, null, filteredCode);
}
public DataItem(int id, Msg msg, ByteType byteType, DataType dataType, int bit, String subject,
@Nullable Unit<?> unit, @Nullable CodeType filteredCode) {
this.id = id;
this.msg = msg;
this.byteType = byteType;
this.dataType = dataType;
this.bitpos = bit;
this.subject = subject;
}
public DataItem(int id, Msg msg, ByteType byteType, DataType dataType, int bit, String subject, Unit<?> unit) {
this(id, msg, byteType, dataType, bit, subject);
this.unit = unit;
this.filteredCode = filteredCode;
}
}

View File

@ -17,10 +17,11 @@ import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.Units;
/**
* The {@link DataItemGroup} represents a list of all possible DataItem messages within the OpenTherm specification.
*
*
* @author Arjen Korevaar - Initial contribution
*/
@NonNullByDefault
@ -31,24 +32,32 @@ public class DataItemGroup {
private static Map<Integer, DataItem[]> createDataItemGroups() {
HashMap<Integer, DataItem[]> g = new HashMap<>();
g.put(0, new DataItem[] { new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 0, "ch_enable"),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 1, "dhw_enable"),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 2, "cooling_enabled"),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 3, "otc_active"),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 4, "ch2_enable"),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 5, "0x00:5"),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 6, "0x00:6"),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 7, "0x00:7"),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 0, "fault"),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 1, "ch_mode"),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 2, "dhw_mode"),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 3, "flame"),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 4, "cooling"),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 5, "ch2E"),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 6, "diag"),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 7, "0x00:7") });
g.put(0, new DataItem[] {
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 0, "ch_enable", CodeType.B),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 0, "ch_enablerequested", CodeType.T),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 0, "ch_enableoverride", CodeType.R),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 1, "dhw_enable", CodeType.B),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 2, "cooling_enabled", CodeType.B),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 3, "otc_active", CodeType.B),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 4, "ch2_enable", CodeType.B),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 5, "0x00:5", CodeType.B),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 6, "0x00:6", CodeType.B),
new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 7, "0x00:7", CodeType.B),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 0, "fault", CodeType.B),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 1, "ch_mode", CodeType.B),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 2, "dhw_mode", CodeType.B),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 3, "flame", CodeType.B),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 4, "cooling", CodeType.B),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 5, "ch2E", CodeType.B),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 6, "diag", CodeType.B),
new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 7, "0x00:7", CodeType.B) });
g.put(1, new DataItem[] {
new DataItem(1, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "controlsetpoint", SIUnits.CELSIUS) });
new DataItem(1, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "controlsetpoint", SIUnits.CELSIUS,
CodeType.B),
new DataItem(1, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "controlsetpointrequested",
SIUnits.CELSIUS, CodeType.T),
new DataItem(1, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "controlsetpointoverride", SIUnits.CELSIUS,
CodeType.R) });
g.put(2, new DataItem[] { new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 0, "0x02:0"),
new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 1, "0x02:1"),
new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 2, "0x02:2"),
@ -105,13 +114,16 @@ public class DataItemGroup {
new DataItem(12, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "0x0c:l") });
g.put(13, new DataItem[] { new DataItem(13, Msg.READ, ByteType.HIGHBYTE, DataType.UINT8, 0, "0x0d:h"),
new DataItem(13, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "0x0d:l") });
g.put(14, new DataItem[] { new DataItem(14, Msg.READ, ByteType.LOWBYTE, DataType.FLOAT, 0, "maxrelmdulevel") });
g.put(14, new DataItem[] {
new DataItem(14, Msg.READ, ByteType.LOWBYTE, DataType.FLOAT, 0, "maxrelmdulevel", Units.PERCENT) });
g.put(15, new DataItem[] { new DataItem(15, Msg.READ, ByteType.HIGHBYTE, DataType.UINT8, 0, "maxcapkw"),
new DataItem(15, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "maxcapprc") });
g.put(16, new DataItem[] {
new DataItem(16, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "roomsetpoint", SIUnits.CELSIUS) });
g.put(17, new DataItem[] { new DataItem(17, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "modulevel") });
g.put(18, new DataItem[] { new DataItem(18, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "waterpressure") });
g.put(17, new DataItem[] {
new DataItem(17, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "modulevel", Units.PERCENT) });
g.put(18, new DataItem[] {
new DataItem(18, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "waterpressure", Units.BAR) });
g.put(19, new DataItem[] { new DataItem(19, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "dhwflow") });
g.put(20, new DataItem[] { new DataItem(20, Msg.READWRITE, ByteType.BOTH, DataType.DOWTOD, 0, "dowtod") });
g.put(21, new DataItem[] { new DataItem(21, Msg.READWRITE, ByteType.HIGHBYTE, DataType.UINT8, 0, "month"),

View File

@ -19,7 +19,7 @@ import org.eclipse.jdt.annotation.Nullable;
/**
* The {@link Message} represent a single message received from the OpenTherm Gateway.
*
*
* @author Arjen Korevaar - Initial contribution
*/
@NonNullByDefault
@ -27,22 +27,12 @@ public class Message {
private static final Pattern messagePattern = Pattern.compile("[TBRA]{1}[A-F0-9]{8}");
/*
* The code field is not part of OpenTherm specification, but added by OpenTherm Gateway.
* It can be any of the following:
*
* T: Message received from the thermostat
* B: Message received from the boiler
* R: Request sent to the boiler
* A: Response returned to the thermostat
* E: Parity or stop bit error
*/
private String code;
private CodeType code;
private MessageType messageType;
private int id;
private String data;
public String getCode() {
public CodeType getCode() {
return this.code;
}
@ -139,8 +129,7 @@ public class Message {
// If the message is a Request sent to the boiler or an Answer returned to the
// thermostat, and it's ID is equal to the previous message, then this is an
// override sent by the OpenTherm Gateway
return other != null && this.getID() == other.getID()
&& ("R".equals(this.getCode()) || "A".equals(this.getCode()));
return other != null && this.getID() == other.getID() && (this.code == CodeType.R || this.code == CodeType.A);
}
@Override
@ -148,7 +137,7 @@ public class Message {
return String.format("%s - %s - %s", this.code, this.id, this.data);
}
public Message(String code, MessageType messageType, int id, String data) {
public Message(CodeType code, MessageType messageType, int id, String data) {
this.code = code;
this.messageType = messageType;
this.id = id;
@ -158,7 +147,7 @@ public class Message {
public static @Nullable Message parse(String message) {
if (messagePattern.matcher(message).matches()) {
// For now, only parse TBRA codes
String code = message.substring(0, 1);
CodeType code = CodeType.valueOf(message.substring(0, 1));
MessageType messageType = getMessageType(message.substring(1, 3));
int id = Integer.valueOf(message.substring(3, 5), 16);
String data = message.substring(5);

View File

@ -208,7 +208,8 @@ public class OpenThermGatewaySocketConnector implements OpenThermGatewayConnecto
}
}
if (msg.getMessageType() == MessageType.READACK || msg.getMessageType() == MessageType.WRITEDATA) {
if (msg.getMessageType() == MessageType.READACK || msg.getMessageType() == MessageType.WRITEDATA
|| msg.getID() == 0 || msg.getID() == 1) {
receiveMessage(msg);
}
}

View File

@ -9,7 +9,7 @@
<label>Room Temperature</label>
<description>Current sensed room temperature</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"></state>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="roomsetpoint">
@ -17,7 +17,7 @@
<label>Room Setpoint</label>
<description>Current room temperature setpoint</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"></state>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="temperaturetemporary">
@ -25,7 +25,7 @@
<label>Temporary Room Setpoint Override</label>
<description>Temporary override room temperature setpoint</description>
<category>Temperature</category>
<state readOnly="false" min="0" max="30" step="0.1" pattern="%.1f %unit%"></state>
<state readOnly="false" min="0" max="30" step="0.1" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="temperatureconstant">
@ -33,15 +33,31 @@
<label>Constant Room Setpoint Override</label>
<description>Constant override room temperature setpoint</description>
<category>Temperature</category>
<state readOnly="false" min="0" max="30" step="0.1" pattern="%.1f %unit%"></state>
<state readOnly="false" min="0" max="30" step="0.1" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="controlsetpoint">
<item-type>Number:Temperature</item-type>
<label>Control Setpoint</label>
<description>Central heating water setpoint</description>
<description>Central heating water setpoint set at boiler</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"></state>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="controlsetpointrequested">
<item-type>Number:Temperature</item-type>
<label>Control Setpoint Requested</label>
<description>Central heating water setpoint requested by Thermostat</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="controlsetpointoverride">
<item-type>Number:Temperature</item-type>
<label>Control Setpoint Override</label>
<description>Central heating water setpoint configured on OTGW</description>
<category>Temperature</category>
<state readOnly="false" min="0" max="100" step="0.1" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="dhwtemp">
@ -49,7 +65,7 @@
<label>Domestic Hot Water Temperature</label>
<description>Domestic hot water temperature</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"></state>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="tdhwset">
@ -57,7 +73,7 @@
<label>Domestic Hot Water Setpoint</label>
<description>Domestic hot water temperature setpoint</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"></state>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="overridedhwsetpoint">
@ -65,7 +81,7 @@
<label>Domestic Hot Water Setpoint Override</label>
<description>Domestic hot water temperature setpoint override</description>
<category>Temperature</category>
<state readOnly="false" min="0" max="100" step="0.1" pattern="%.1f %unit%"></state>
<state readOnly="false" min="0" max="100" step="0.1" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="flowtemp">
@ -73,7 +89,7 @@
<label>Boiler Water Temperature</label>
<description>Boiler water temperature</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"></state>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="returntemp">
@ -81,7 +97,7 @@
<label>Return Water Temperature</label>
<description>Return water temperature</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.1f %unit%"></state>
<state readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="outsidetemp">
@ -89,126 +105,139 @@
<label>Outside Temperature</label>
<description>Outside temperature</description>
<category>Temperature</category>
<state readOnly="false" min="-40" max="100" step="0.1" pattern="%.1f %unit%"></state>
<state readOnly="false" min="-40" max="100" step="0.1" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="waterpressure">
<item-type>Number:Dimensionless</item-type>
<label>Central Heating Water Pressure</label>
<description>Central heating water pressure</description>
<state readOnly="true" pattern="%.1f bar"></state>
<state readOnly="true" pattern="%.1f bar"/>
</channel-type>
<channel-type id="ch_enable">
<item-type>Switch</item-type>
<label>Central Heating Enabled</label>
<description>Central heating enabled</description>
<state readOnly="true"></state>
<description>Central heating enabled set at boiler</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="ch_enablerequested">
<item-type>Switch</item-type>
<label>Central Heating Enabled Thermostat</label>
<description>Central heating enabled requested by thermostat</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="ch_enableoverride">
<item-type>Switch</item-type>
<label>Central Heating Overridden</label>
<description>Central heating enabled overridden at OTGW</description>
</channel-type>
<channel-type id="ch_mode">
<item-type>Switch</item-type>
<label>Central Heating Active</label>
<description>Central heating active</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="dhw_enable">
<item-type>Switch</item-type>
<label>Domestic Hot Water Enabled</label>
<description>Domestic hot water enabled</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="dhw_mode">
<item-type>Switch</item-type>
<label>Domestic Hot Water Active</label>
<description>Domestic hot water active</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="flame">
<item-type>Switch</item-type>
<label>Burner Active</label>
<description>Burner active</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="modulevel">
<item-type>Number:Dimensionless</item-type>
<label>Relative Modulation Level</label>
<description>Relative modulation level</description>
<state readOnly="true" pattern="%.1f %%"></state>
<state readOnly="true" pattern="%.1f %%"/>
</channel-type>
<channel-type id="maxrelmdulevel">
<item-type>Number:Dimensionless</item-type>
<label>Maximum Relative Modulation Level</label>
<description>Maximum relative modulation level</description>
<state readOnly="true" pattern="%.1f %%"></state>
<state readOnly="true" pattern="%.1f %%"/>
</channel-type>
<channel-type id="fault">
<item-type>Switch</item-type>
<label>Fault Indication</label>
<description>Fault indication</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="servicerequest">
<item-type>Switch</item-type>
<label>Service Required</label>
<description>Service required</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="lockout-reset">
<item-type>Switch</item-type>
<label>Lockout-Reset Enabled</label>
<description>Lockout-reset enabled</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="lowwaterpress">
<item-type>Switch</item-type>
<label>Low Water Pressure Fault</label>
<description>Low water pressure fault</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="gasflamefault">
<item-type>Switch</item-type>
<label>Gas Or Flame Fault</label>
<description>Gas or flame fault</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="airpressfault">
<item-type>Switch</item-type>
<label>Air Pressure Fault</label>
<description>Air pressure fault</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="waterovtemp">
<item-type>Switch</item-type>
<label>Water Over-Temperature Fault</label>
<description>Water over-temperature fault</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="oemfaultcode">
<item-type>Number:Dimensionless</item-type>
<label>OEM Fault Code</label>
<description>OEM fault code</description>
<state readOnly="true"></state>
<state readOnly="true"/>
</channel-type>
<channel-type id="sendcommand">
<item-type>String</item-type>
<label>Send Command</label>
<description>Channel to send commands to the OpenTherm Gateway device</description>
<state readOnly="false"></state>
<state readOnly="false"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -12,6 +12,8 @@
<channel id="temperaturetemporary" typeId="temperaturetemporary"/>
<channel id="temperatureconstant" typeId="temperatureconstant"/>
<channel id="controlsetpoint" typeId="controlsetpoint"/>
<channel id="controlsetpointrequested" typeId="controlsetpointrequested"/>
<channel id="controlsetpointoverride" typeId="controlsetpointoverride"/>
<channel id="dhwtemp" typeId="dhwtemp"/>
<channel id="tdhwset" typeId="tdhwset"/>
<channel id="overridedhwsetpoint" typeId="overridedhwsetpoint"/>
@ -20,6 +22,8 @@
<channel id="outsidetemp" typeId="outsidetemp"/>
<channel id="waterpressure" typeId="waterpressure"/>
<channel id="ch_enable" typeId="ch_enable"/>
<channel id="ch_enablerequested" typeId="ch_enablerequested"/>
<channel id="ch_enableoverride" typeId="ch_enableoverride"/>
<channel id="ch_mode" typeId="ch_mode"/>
<channel id="dhw_enable" typeId="dhw_enable"/>
<channel id="dhw_mode" typeId="dhw_mode"/>