Edit: Updated for OH 4
Please see Design Pattern: What is a Design Pattern and How Do I Use Them for a desciption of DPs.
Problem Statement
Often one will encounter a situation where a device needs to be turned on/off based on a sensor reading but sensors are inherently noisy, sometimes jumping up a little bit and then jumping down a little bit on each reading.
In the naive approach one sets a threshold with a simple:
var newCommand = 'OFF';
if(items.MySensor.quantityState.greaterThan(items.MySetpoint.quantityState)) {
newCommand = 'ON';
}
items.MyDevice.sendCommand(newCommand);
However, when using this approach. if the sensor happens to be sitting around the setpoint value, it will bounce above and below rapidly causing the device to rapidly turn on and off. This is often undesireable.
Concept
Provide a “dead zone”, called hysteresis, in which changes in the sensor reading does not cause a change in the device.
For example, let’s say we have a heater with a setpoint of 70 °F. When the temperature is below 70 °F we want to turn on the heater and when it’s above 70 °F we want to turn it off.
Hysteresis Profile
Link the temperature sensor Channel to a Switch Item and on the link apply the hysteresis profile. This profile will implement the hysteresis, commanding the Switch to ON or OFF as configured.
JavaScript
var newCommand = 'STAY';
if(items.MyTemp.quantityState.lessThan(Quantity('68 °F'))) {
newCommand = 'ON';
}
else if(items.MyTemp.quantityState.greaterThan(Quantity('70 °F'))) {
newCommand = 'OFF';
}
if(newCommand != 'STAY') {
items.MyHeater.sendCommand(newCommand);
}
Note, the code could be made more concise as the following.
if(items.MyTemp.quantityState.lessThan(Quantity('68 °F'))) {
items.MyHeater.sendCommand('ON');
else if(items.MyTemp.quantityState.greaterThan(Quantity('70 °F'))) {
items.MyHeater.sendCommand('OFF');
}
But, by waiting to the end of the rule to send the command in only one place, you have the opportunity to add additional logic without repeating it. For example, to only command the heater if it’s not already in the desired state:
var newCommand = 'STAY';
if(items.MyTemp.quantityState.lessThan(Quantity('68 °F'))) {
newCommand = 'ON';
}
else if(items.MyTemp.quantityState.greaterThan(Quantity('70 °F'))) {
newCommand = 'OFF';
}
if(newCommand != 'STAY' && newCommand != items.MyHeater.state) {
items.MyHeater.sendCommand(newCommand);
}
Advantages and Disadvantages
There are all sorts of approaches to keep a device from flapping. This approach works best when the sensor is measuring something that tends to change relatively slowly like temperature or humidity. The wider the hysteresis buffer, the longer it should take for a device to turn on or off as the sensor reading will take more time to reach the lower or upper thresholds.