Note: First of all, when I put “Design Pattern(?):” at the beginning of a post, I’m putting it up for discussion. I’m only making suggestions here, not offering a complete solution.
Sensor Fusion Proxy Pattern
Background
There are officially no dedicated design patterns for sensor fusion or Kalman filters in openHAB. The existing design patterns in the openHAB community tend to focus on topics such as proxy items, group behaviors, expiration timers, and rule organization, but not on mathematical signal processing.
Why doesn’t this exist (yet)?
openHAB itself is primarily an integration and orchestration platform. It brings together numerous protocols/technologies (KNX, Zigbee, Z-Wave, MQTT, etc.) and enables automation.
Complex filtering or fusion algorithms are rarely built directly into it, as they typically run better in a dedicated computing environment (e.g., Python, Node-RED, InfluxDB with capacity queries, edge devices such as ESP32).
But: You can invent a design pattern for it
One could propose a “Sensor Fusion Proxy Pattern” for openHAB. Idea:
- Raw Sensors → Items with raw values (e.g., temperature from multiple sensors).
- Pre-Processing → Small scripts/rules in openHAB or externally (Jython/JS scripting, Node-RED, MQTT broker, Python script with Kalman).
- Fusion Item (Proxy) → The result of the fusion (e.g., “Filtered_Temperature”) is written to a new item.
- Automations only use the proxy item, never the raw data.
This would be analogous to other patterns (such as the Proxy Item Pattern), except that the “proxy” here is a fusion/filter output.
Example of an implementation idea
- Items:
Temp_Sensor1,Temp_Sensor2,Temp_Fused - Rule (pseudocode in JS scripting):
var s1 = items.getNumber("Temp_Sensor1");
var s2 = items.getNumber("Temp_Sensor2");
var fused = (s1 + s2) / 2; // simple fusion
events.postUpdate("Temp_Fused", fused);
-
For more complex things (Kalman, Extended Kalman, Particle Filter):
-
Either a binding to an external process (Python script via MQTT or REST).
-
Or a rule script in GraalJS/Jython with a Kalman library.
Proposal for a new design pattern
“Sensor Fusion Proxy Pattern”
- Motivation: Use of multiple uncertain sensors, smoothing/filtering of measured values.
- Structure: Raw items → fusion rule → proxy item → automations.
- Variant: Simple fusion (mean, median) vs. complex (Kalman, ML approaches).
- Best practice: Outsource computationally intensive tasks, use a proxy only for integration.
Design Pattern: Sensor Fusion Proxy Pattern
Motivation / Problem
Many smart home sensors provide measurements that are noisy, inaccurate, or vary. To create reliable automations, this raw data must be filtered or merged. openHAB doesn’t offer special filters like Kalman out of the box, but sensor fusion can be implemented using rules or external services.
Goal:
- Combine multiple raw sensors into a single, reliable value.
- Automations only work with the filtered values.
- Computationally intensive filters (e.g., Kalman) can be outsourced.
Solution / Pattern
“Sensor Fusion Proxy Pattern”
Structure:
- Raw Items: Represent the unprocessed sensor values.
Temp_Sensor1
Temp_Sensor2
Temp_Sensor3
- Fusion Rule / Script / Process: Calculates the filtered value from the raw sensors.
- Proxy Item: Stores the result of the fusion. Automations access this item exclusively.
Temp_Fused
- Automations / Visualization: Uses
Temp_Fusedinstead of the raw sensors.
Implementation options
1. Internal openHAB DSL Rule
Simple mean approach:
rule "Fuse temperature sensors"
when
Member of gTemperatureSensors changed
then
var sum = 0.0
var count = 0
gTemperatureSensors.members.forEach[ sensor |
val value = sensor.state as Number
if(value != null) {
sum += value.doubleValue
count += 1
}
]
if(count > 0) {
val fused = sum / count
Temp_Fused.postUpdate(fused)
}
end
gTemperatureSensorsis a group of all raw sensor items.- Advantage: No external dependencies.
- Disadvantage: No complex filters (Kalman).
2. Jython Scripting (Rule Engine)
For more flexible logic, e.g. E.g. moving average or Kalman filter integration:
from core.rules import rule
from core.triggers import when
from core.actions import ScriptExecution
last_value = None
alpha = 0.5 # einfacher Low-Pass Filter
@rule("Fuse temperature sensors Jython")
@when("Member of gTemperatureSensors changed")
def fuse_temperature(event):
global last_value
values = [item.state for item in gTemperatureSensors.members if item.state is not None]
if values:
avg = sum(values)/len(values)
if last_value is None:
filtered = avg
else:
filtered = alpha * avg + (1-alpha) * last_value
last_value = filtered
Temp_Fused.postUpdate(filtered)
3. JavaScript Scripting (GraalJS)
var members = gTemperatureSensors.members;
var sum = 0;
var count = 0;
for (var i = 0; i < members.length; i++) {
var value = members[i].state;
if (value != null) {
sum += value;
count += 1;
}
}
if (count > 0) {
var fused = sum / count;
Temp_Fused.postUpdate(fused);
}
4. Node-RED
-
Node-RED can act as an external rule engine system.
-
openHAB Nodes:
events: state→ Triggers when a sensor changes.- Function Node → Fusion/Filter:
let values = [msg.payload.Temp_Sensor1, msg.payload.Temp_Sensor2]; let fused = values.reduce((a,b) => a+b,0) / values.length; msg.payload = {Temp_Fused: fused}; return msg;openHAB out→ UpdateTemp_Fused.
-
Advantage: Visual, external logic, easy use of complex filters.
5. MQTT + External Python Script with Kalman Filter
Setup:
- Sensors publish their values via MQTT:
home/sensor/temperature1 home/sensor/temperature2 - openHAB subscribes to the filtered value:
Temp_Fused -> MQTT Topic: home/sensor/temperature/fused - Python Kalman Script:
import paho.mqtt.client as mqtt
from filterpy.kalman import KalmanFilter
import numpy as np
kf = KalmanFilter(dim_x=1, dim_z=1)
kf.x = np.array([[20]]) # Initial
kf.P *= 1000
kf.F = np.array([[1]])
kf.H = np.array([[1]])
kf.R = 2
kf.Q = 0.1
def fuse(values):
for v in values:
kf.predict()
kf.update(v)
return kf.x[0,0]
def on_message(client, userdata, msg):
payload = [float(x) for x in msg.payload.decode().split(',')]
fused = fuse(payload)
client.publish("home/sensor/temperature/fused", fused)
client = mqtt.Client()
client.on_message = on_message
client.connect("localhost",1883,60)
client.subscribe("home/sensor/temperature")
client.loop_forever()
- openHAB receives the already filtered value via MQTT-Thing:
Number Temp_Fused "Fused Temperature [%.1f °C]" {channel="mqtt:topic:broker:temp_fused"}
Best Practices
- Use proxy items: Automations never access raw sensors directly.
- Outsource computationally intensive filters: Node-RED or Python for Kalman/ML filters.
- Logging / Monitoring: Write fused values to a persistent database (InfluxDB) to check filter quality.
- Fallbacks: If sensors fail, fusion should remain robust (e.g., median instead of mean).
- Documentation: Clearly name raw sensors, fusion algorithm, and proxy items, e.g.,
Temp_Sensor1→Temp_Fused.
How does the Sensor Fusion Proxy Pattern differ from the Sensor Aggregation Pattern and Bayesian Sensor Aggregation?
My proposed “Sensor Fusion Proxy Pattern” with the two existing openHAB patterns:
Sensor Fusion Proxy Pattern vs. Sensor Aggregation
| Feature | Sensor Fusion Proxy Pattern | Sensor Aggregation Pattern |
|---|---|---|
| Goal | Merge multiple sensors into a filtered, stable value (e.g., mean, Kalman) | Combine multiple sensors logically, e.g., OR, AND for presence or switch states |
| Type of processing | Mathematical filters, statistical fusion, external algorithms if necessary | Logical combination of sensor states |
| Complexity | Medium to high, depending on filter/algorithm | Low |
| Handling of uncertainty | Considers sensor uncertainties, noise, and outliers | No uncertainty handling, only binary or group-based |
| Examples | Temperature fusion with Kalman, combined humidity or brightness values | Motion detector: “If anyone reports → presence” |
Conclusion:
My pattern extends the classic Sensor Aggregation pattern with filtering, smoothing, and uncertainty handling. While Sensor Aggregation simply aggregates, Sensor Fusion goes a step further: “How can I intelligently merge the data, not just combine it?”
Sensor Fusion Proxy Pattern vs. Bayesian Sensor Aggregation
| Feature | Sensor Fusion Proxy Pattern | Bayesian Sensor Aggregation |
|---|---|---|
| Goal | General sensor fusion: stabilization, smoothing, combined values | Probabilistic evaluation of sensors to calculate probabilities for states |
| Type of processing | Filter-based: mean, median, low-pass, Kalman, etc. | Bayesian calculations, weighting of sensor probabilities |
| Complexity | Medium to high (with Kalman) | High (Bayesian logic, probability theory) |
| Handling of uncertainty | Yes, via filters/statistics, but not probabilistic | Yes, probabilistic; sensor reliability explicitly modeled |
| External processing | Optional (Python, Node-RED, MQTT) | Optional, usually Jython or external calculations required |
| Examples | Filtered temperature or humidity | Presence detection with probabilities from multiple sensors |
Conclusion:
Bayesian Sensor Aggregation is more specific: It concerns the probability of a state based on uncertain sensors.
Sensor Fusion Proxy Pattern is more general: The goal is smoothing, filtering, and merging measured values. Bayesian Aggregation could even be considered a special variant of Sensor Fusion.
Summary
- Sensor Aggregation: Simple logical combination → no uncertainty handling.
- Sensor Fusion Proxy Pattern (new): Mathematical fusion/filtering → stabilized values, outlier handling, smoothing.
- Bayesian Sensor Aggregation: Probabilistic fusion → evaluates the probability of states, explicitly for uncertain sensors.
So: My pattern is a flexible “all-rounder” that can accommodate simple averages, Kalman filters, or even Bayesian logic. It’s less about the probability of a state and more about reliable, fused measurements that can be used by automation.
Comparison diagram
The diagram shows the Sensor Fusion Proxy Pattern, the Sensor Aggregation Pattern, and the Bayesian Aggregation Pattern side by side and visualizes the data flows – making the difference immediately visible.
Here’s the diagram showing the differences:
- Left: Sensor Aggregation → simple logical connection.
- Middle: Sensor Fusion Proxy Pattern → mathematical filtering/fusion, including Kalman.
- Right: Bayesian Sensor Aggregation → probabilistic evaluation.
- Bottom: All lead to a common proxy item that is used in automations.
