In this tutorial, I’m going to update for OH4 the system I introduced in OH3 for managing items which use Bayesian probabilities for determining a particular binary status.
You can find the components of the OH3 version here:
WARNING:
These rules and widget are no longer actively maintained. They will work for many OH3 versions and in some cases, the forum threads include suggestions for manually updating the individual components for later OH3 versions.
Credit:
This is an implementation of @cweitkamp’s awesome Bayesian aggregation design pattern. So, much of the credit goes to him and you will want to read through his post for a more detailed explanation of the underlying concepts and very clear description and example of probability selection.
WARNING:
There are breaking changes in the configuration from OH3 versions of this system. However, OH3 sensors will be automatically updated to the newer configuration the first time they are audited (see
Auditing the sensor configuration
below) or the first time the sensor is activated, so no action is required on the users part.
Introduction
Bayesian probability is a method of determining the likelihood of an event based on a prior understanding of how likely it is that different factors contribute to that event. This is useful in home automation because this enables the user to capture as an event or state more complex situations than basic binary sensors or probabilities.
As a basic example, consider an automation that changes the home from day mode to night mode. A basic home automation might just set night mode at 10PM. But sometimes I go to bed early and sometimes I stay up late, so that’s not very useful. I need the decision tree to include my behavior as well. So now the automation could look like:
when bedroom light is turned on then set night mode
It should be clear immediately why this is insufficient. If I get up early in the morning and it is still dark out, I will turn the bedroom light on, but it is not night time. That automation has to increase in complexity:
when bedroom light is turned on and after 6PM then set night mode
But, I often go into my bedroom to get something during the evening which requires me to turn on the light even if I am not getting ready for bed yet. This simple idea of the system in night mode or not can depend on an very large number of factors that may or may not come into play each night: time, status of motion, lights, and room presence in the house, weekend or weekday, guests in the house, is a movie playing on one of the TVs, is the front door locked, is the car in the garage…etc.
One solution is certainly to just continue to build out the automation decision tree to accommodate all the different possible combinations of inputs, but this grows roughly exponentially depending on the inputs. A Bayesian sensor provides a second possible solution to this where each of the possible inputs can be assigned a probability that it coincides with the desired event and the likelihood of the event is determined by the combination of each of those input states and their probabilities. When each of the contributing factors have been aggregated into a final probability, that probability can be compared to a threshold value to determine whether an event or state has been achieved. If it’s 10:15 PM on a weekday, and the kitchen light is off, even if I forgot to lock the front door, when I turn on the bedroom light there’s a 96% probability that it is night time and that’s higher than a 95% threshold so the automation system gets the event that nighttime has arrived.
Basic setup
This system requires two items for each Bayesian sensor, with the option for a third.
- Group item (required) - sensor settings and group for all items to be included in probabilities
- Proxy item (required) - (usually a Switch) Item to hold the final state of the decision (“Is the final probability greater than the threshold?”)
- Posterior item (optional) - Number item to hold the most recently calculated probability (only included if you want to know the most recent calculated probability or persist and track the probability over time)
One rule is required to process the probabilities when item states change. Optionally, creating and configuring these items can be achieved through two UI interfaces that interact with an second rule. Each of these components can be installed directly from the marketplace, but there is a little additional configuration required:
Marketplace threads for the rules and widgets can be found here:
- Rules
- Bayesian sensor activation (required)
- Bayesian sensor management (recommended)
- Widgets
- Bayesian sensor list (recommended)
- Bayesian sensor details (recommended)
UI install and setup
Use the Add-on Store
on your openHAB Administration to access the marketplace and install the requirements.
- These rules require that the JSScripting add-on is installed. This add-on is found under
Automation
→Languages & Technologies
- The rules are found under
Automation
→Rule Templates
- The widgets are found under
User Interfaces
→Widgets for the Main UI
.
Rules
You will only need 1 copy of each rule.
- Bayesian sensor activation - Create a new rule using
Settings
→Rules
→+
and selectBayesian sensor activation
from the list under theCreate from Template
heading.- Give the rule any ID that you like.
- Give the rule any Name that you like.
- You can save the rule without a trigger for now. You will configure a trigger for this rule after you have created your first sensor.
- Bayesian sensor management - Create a new rule using
Settings
→Rules
→+
and selectBayesian sensor management
from the list under theCreate from Template
heading.- Give the rule an ID. It may be any ID that you like, but if you use the ID
bayesian_widget_management
then it will be automatically detected by the widgets. If you use a custom ID you will have to configure the widgets to use that custom ID. - Give the rule any Name that you like.
- You do not have to configure anything else for this rule. It does not have a trigger it will only ever be called directly from the widgets.
- Give the rule an ID. It may be any ID that you like, but if you use the ID
The first time this rule runs it will create an item named
Widget_Settings_Bayesian_Sensor_Details
. This item allows the details widget to refresh when this rule is run. You do not ever have to interact with this item, and if it gets deleted it will just get recreated the next time this rule runs.
Widgets
Bayesian sensor details
This widget is designed to emulate the appearance of the standard OH MainUI configuration details pages. This means that it works best when added to a page by itself. For example:
config:
label: Settings - Bayesian Sensor Details
blocks:
- component: oh-block
config: {}
slots:
default:
- component: oh-grid-row
config: {}
slots:
default:
- component: oh-grid-col
config: {}
slots:
default:
- component: widget:jag_bayesian_sensor_details
config:
manageRule: custom_rule_name_here
sensor: =vars.bayesianItem || 'some_sensor_name'
grid: []
canvas: []
You may give this page any Page ID that you like, however the recommended ID is
settings_bayesian_details
. If you use this ID then then the sensor list widget will find it automatically and you do not need to configure that widget’sdetailPage
property.
Widget Configuration On Page
Parameter | Required | Explanation |
---|---|---|
sensor | Yes | This must be set to =vars.bayesianItem for the page to load the correct sensor item when opened. It will not show anything on the page if this is not set. The rest of the expression in the example above adds some_sensor_name if you want a default sensor to be shown (for example, on this page test viewer) |
manageRule | No | Only set this configuration if you have given the bayesian sensor management rule an ID that is NOT bayesian_widget_management |
useLabel | No | By default, the observatin list shows the labels of the observations item. Set this to false to display the item names instead |
Bayesian sensor list
This widget is designed to emulate the appearance of the standard OH MainUI configuration list pages. This means that it works best when added to a page by itself. For example:
config:
label: Settings - Bayesian Sensors
blocks:
- component: oh-block
config: {}
slots:
default:
- component: oh-grid-row
config: {}
slots:
default:
- component: oh-grid-col
config: {}
slots:
default:
- component: widget:jag_bayesian_sensor_list
config:
manageRule: custom_rule_name_here
detailPage: custom_detail_page_id_here
grid: []
canvas: []
You may give this page any Page ID that you like.
Widget Configuration On Page
Parameter | Required | Explanation |
---|---|---|
detailPage | No | Only set this configuration if you have given the bayesian detail page an ID that is NOT bayesian_widget_management |
manageRule | No | Only set this configuration if you have given the bayesian sensor management rule an ID that is NOT settings_bayesian_details |
Each item in the list shows you the label and name of the sensor item. On the right side, the chip includes an icon indicating the result of the most recent configuration audit (see Auditing the sensor configuration below) the current calculated probability and the set threshold for that sensor. If the details widget has been configured and added to a page properly, then clicking on any item will open the details page for that particular sensor item.
Manual install and setup
If you do not wish to use the UI widgets for management of you bayesian sensors then you only need to install the activation rule as described above. You can create the sensor items manually either in the UI or .items files following the Configuration settings described below.
Creating Bayesian Sensors
Creation of bayesian sensors with basic settings and adding pre-existing items as simple observations can be handled entirely though the UI widgets. More advanced features can be set using the full metadata after initial creation.
Create a sensor
Open the sensors list page and click on the blue +
icon in the lower right corner. This will give you two options:
- Create New Group - Creates a group to be a bayesian sensor and initializes the basic metadata. Can also create associated items.
- Create From Existing - Initializes the basic metadata for a group item that already exists. Does not create any other items.
For this tutorial, select Create New Group
and a dialog will come up:
Field | Required | Default | Explanation |
---|---|---|---|
Name | Yes | none | This will be the name of the Group Item that holds the bayseian sensor configuration. There is no default for this value, you must provide a valid OH Item name. |
Label | No | New Bayesian Group | This will be the label of the group item itself |
New Proxy Item | No | checked | A proxy item is also required for the bayesian function so if the New Proxy Item option is selected this will create a Switch Item with the name {NameField}_Proxy at the same time the group is created. |
New Posterior Item | No | unchecked | A posterior item is not required for the bayesian function, but if you want to know the probability or track it over time select this to create a Number Item with the name {NameField}_Posterior at the same time the group is created. |
When a new sensor is created in this manner, then in the sensor list you will see a new item that looks like:
Note that this indicates that no audit has been run on the new configuration (that must be done manually) and it currently has no calculated value (there’s nothing to calculate yet). But we can click on the item to open up its details page:
For this tutorial, proxy and posterior items were automatically generated and associated with the sensor. You can also see the default values that are assigned to various important configuration parameters. There are also no observation items included in this sensor yet, so before this sensor can work we must add some.
Add an observation
In order for an item to contribute as a valid observation for a sensor there must be information about that observation in the sensor’s metadata, and that item must be a member of the sensor group. You can, of course, do this manually but the widget also gives you a short cut for this.
Click on the Add Observation Item
and it will turn into a simple input that allows you to type in the name of the item you wish to include in the sensor. This does not create a new item, you must supply the name of an item that already exists. Cancel the new observation with the X
button or accept it with the check.
Accepting the new observation will update the metadata and add the item to the sensor group. This means that the new observation will now appear in the list of the sensor’s observations with some basic information available: The item label, the operation that tests whether the observation is true (e.g., eq
for equality), the state that will result in a true observation, and what the item’s current value is.
To manage the observation, swipe to the right on the list item and you will see three buttons:
- Delete - Removes this observation from the sensor (does not delete the item)
- Edit - Opens a small observation editing form
- Link - Opens the standard OH details page for the item
You can edit the test and true state settings, as well as the observation’s true and false probabilities. There are more advanced options for the observations as well, but these you will need to set by editing the metadata directly.
Auditing the sensor configuration
Due to the amount and complexity of possible configuration, the system offers a method to verify the accuracy of a sensor’s configuration by running a configuration audit. Press the Audit Configuration
button at the bottom of the details page and many common errors with be checked for. The results of the Audit will display in the OH logs and on the sensor details page itself. For example, the proxy item must be configured using the proxy
sensor propery and if it is not this results in an error, whereas the sensor’s state when true (the sensor’s probability has exceeded the threshhold) has a possible default value of ON
and will only result in a warning if it is missing:
We can use the Edit Metadata
to fix these two issues and the sensor will fully pass when the audit is run again:
Enabling a sensor
At this point, the sensor will still never calculate a probability and change it’s proxy item. For this final step we have to add the sensor as a trigger to the Bayesian sensor activation
rule. The effect we want is for the sensor to be recalculated any time one of the observation items changes it’s state. Because all the observation items are members of the sensor group, this is easy to do.
Edit the rule and add an item trigger, selecting the sensor item itself and had a memeber change
At this point, your sensor should be fully functional. When one of the observation items changes the sensor’s probability will be recalculated, and the proxy item will change (or not) accordingly.
Configuration Reference
Main group configuration options
Each of the following options is set in the metadata config
:
Config option | Required | Explanation |
---|---|---|
proxy | yes | The name of the item that will receive commands based on the result of the probability calculation |
threshold | yes | Numerical value between 0 and 1 that defines the boundary between the sensor being probably true and probably false |
trueState | no | The command to be sent to the proxy item when the calculated probability is greater than or equal to the threshold (default = ON ) |
falseState | no | The command to be sent to the proxy item when the calculated probability is less than the threshold (default = OFF ) |
prior | no | The initial likelihood that the sensor is in a true state (default = 0.5 ) |
posterior | no | The name of a item (type: Number:dimensionless) in which to store the calculated posterior probability of the sensor |
obs | yes | Map of the individual items to be checked to compute the probability with the name of each item as a key (see Observation item configuration options below) |
Audit
If you have used the widget and widget rule to check the metadata configuration then an audit
property will also be found in the config
metadata. You never have to add this property yourself it will be automatically generated. If the configuration contains no errors or warnings then the property will indicate that the configuration passed, otherwise it will show the errors and warnings. You can delete this key and its values if you wish without impacting the function of the Bayesian group, but the widget will not be able to show the results of the most recent audit if you do.
Observation item configuration options
For each item in the obs
map the following options are available:
Sensors option | Required | Explanation |
---|---|---|
testState | yes | The state relevant for the check of whether the item represents a true or false observation: value type depends on testType |
pTrue | yes | Numerical value from 0 to 1 representing the probability that the main condition is true if this observation is true |
pFalse | yes | Numerical value from 0 to 1 representing the probability that the main condition is true if this observation is false |
testType | no | Short code specifying the kind of test performed on the item state (default test is basic equality) see table below for full list of options |
decay | no | Map of options detailing time-based decrease in pTrue value, see table below for full list of map values |
If testType
is not specified then a basic test of equality between the item state and testState
is performed and the observation is true if the equality is true. Other tests are defined using the testType
as follows:
testType value | testState value | Test performed |
---|---|---|
gt | numerical value | true if item state is greater than testState |
lt | numerical value | true if item state is less then testState |
bt | two-element array of numerical values | true if item state is greater than first array element and less than second array element |
neq | any valid state | true if item state is not equal to testState |
list | array of any length and element type | true if item state is equal to any element in testState |
The decay
property causes the probability if true value (pTrue
) of an observation to decrease over time from some reference time. Usually this will be the last time the item was changed but could be from some absolute time of day or other time point. This requires that there be an additional Type:DateTime Item that holds the timestamp of interest (the timestamp profile being the most obvious way of creating this).
Decay configuration | Required | Explanation |
---|---|---|
decayStep | yes | Numerical value between 0 and 1 to reduce the pTrue value with each timeStep |
timestamp | no | Item name of the DateTime item that holds timestamp value (default is sensor item name with ‘_TS’ appended to the end) |
timeStep | no | Number of minutes between each decrement of the pTrue value (default = 5 minutes) |
decayMin | no | Numerical value between 0 and 1 representing the minimum value that pTrue can be decreased to (default = 0.6) |
Examples
Here is an example of a properly configured BayesianSensor
metadata with some annotations to help understand.
value: " "
config:
proxy: Occupancy_Kitchen
trueState: ON
falseState: OFF
obs:
Occupancy_Kitchen_Detection: #Item that indicates if the camera that sees kitchen area has detected a person
pFalse: 0.2 #The camera also sees a few other areas such as the backyard through the back door
pTrue: 0.9 #If a person has been detected by the camera it is very likely that there is a person in the kitchen
testState: ON
Speaker_Kitchen_Playing: #Switch indicating if sonos speaker is playing
pFalse: 0.3 #Sometimes kitchen speaker is linked to other speakers in the house
pTrue: 0.75 #Usually if the speaker in the kitchen is playing, someone is in the kitchen
testState: ON
Switch_BreakfastLight_OnOff: #Light over the table in the adjoining breakfast space
pFalse: 0.4
pTrue: 0.9
testState: ON
decay: #Kids have the tendency to leave the light on so over time this decreases the probability that this light correlates with someone in the kitchen area
timestamp: Switch_BreakfastLight_OnOff_TS #Name of the DateTime item that holds the last changed timestamp for the light switch
timeStep: 5 #Decrease every five minutes
decayStep: 0.05 #Decrease probability by 5%
decayMin: 0.4 #If the light has been on long enough it hits a minimum equal to `pFalse` which means this observation has no impact on the final probability
Switch_KitchenLight_OnOff:
pFalse: 0.3
pTrue: 0.9
testState: ON
decay:
timestamp: Switch_KitchenLight_OnOff_TS
timeStep: 5
decayStep: 0.05
decayMin: 0.4
AutomationTime: #My system's time of day item
testType: list #Check if the item state is equal to any of the elements in the given array
pFalse: 0.1
pTrue: 0.5
testState: #Array of times of day we are likely to be in the kitchen (rarely is someone in the kitchen after bedtime or before the start of the morning
- MORNING
- AFTERNOON
- EVENING
prior: 0.3 #Baseline probability that someone is in the kitchen at any one time (my wife likes to cook a lot so someone is in the kitchen often)
audit: #This metadata has been checked by the widget rule
passed: true #The metadata is properly formatted
posterior: Occupancy_Kitchen_Posterior #Each time a new probability is calculated it is stored in this item
threshold: 0.95 #A high level of certainty (95% certain) is required to set the kitchen occupancy to ON
This next example is for a switch that triggers my time of day item to change over from WAKE_UP
to MORNING
. Over the years this has proven to be a very difficult task for the system to work out because of so many different possibilities between me, my wife, kids, weekdays and weekends, but this Bayesian group sensor is exceptionally accurate, even with only simple equality tests for all the different sensor observations.
value: " "
config:
proxy: AutomationTime_Morning_Start
obs:
AutomationTime:
pFalse: 0.3
pTrue: 0.99
testState: WAKE_UP
Phone_JustinsCell_ChargingState:
pFalse: 0.5
pTrue: 0.75
testState: OFF
Sensor_MasterBath_Motion:
pFalse: 0.5
pTrue: 0.9
testState: ON
Sensor_MasterCloset_Motion:
pFalse: 0.5
pTrue: 0.8
testState: ON
Switch_MasterBedroomFan_OnOff:
pFalse: 0.5
pTrue: 0.9
testState: OFF
prior: 0.5
audit: #This metadata has been checked by the widget rule
warnings: #Two warnings have cropped up with this configuration for values that I have not specified and so are falling back to the default values instead.
number: 2
list:
"0": trueState not set - default ON will be used
"1": falseState not set - default OFF will be used
posterior: AutomationTime_Morning_Start_Posterior
threshold: 0.9