← Back to Blog

Home Assistant Presence Detection: Combining Multiple Sensors for Reliability

5 min read By Charles

Presence detection is the foundation of useful home automation. Lights that turn on when you arrive, thermostats that adjust when you leave, security that arms automatically—all depend on reliably knowing who’s home.

Single-source presence detection fails. Phones lose connectivity, motion sensors miss still people, GPS drifts. The solution is sensor fusion: combining multiple imperfect signals into reliable presence.

The Sensor Stack

Each sensor type has strengths and weaknesses:

Phone-Based Detection

Home Assistant Companion App

  • GPS geofencing
  • WiFi BSSID connection
  • Bluetooth beacons

Strengths: Accurate location, works away from home Weaknesses: Battery drain, forgetful users, guests without app

Network-Based Detection

Router Integration (UniFi, etc.)

  • Device connection status
  • DHCP tracking

Strengths: Works with any device, no app needed Weaknesses: Doesn’t detect room, slow to register departure

Motion Sensors

PIR and mmWave

  • Immediate room-level detection
  • No app or phone needed

Strengths: Catches everyone, instant response Weaknesses: Can’t identify individuals, misses still people (PIR)

Door Sensors

Contact Sensors

  • Entry/exit events
  • Definitive state changes

Strengths: Unambiguous events Weaknesses: Doesn’t know who or direction

Sensor Fusion Architecture

The goal is a single binary_sensor.someone_home that’s reliably true when anyone is home and false when empty.

Individual Sensors

# configuration.yaml

# Phone tracking
device_tracker:
  - platform: mobile_app

# Router tracking (UniFi example)
device_tracker:
  - platform: unifi
    host: 10.0.1.1

# Motion sensors are already binary_sensors from integration

Person Entity

Group multiple trackers per person:

person:
  - name: Charles
    id: charles
    device_trackers:
      - device_tracker.charles_phone_app
      - device_tracker.charles_phone_wifi
      - device_tracker.charles_watch

Bayesian Sensor

Combine signals probabilistically:

binary_sensor:
  - platform: bayesian
    name: "Someone Home"
    prior: 0.6  # 60% prior probability someone is home
    probability_threshold: 0.9
    observations:
      # Person entities
      - entity_id: person.charles
        prob_given_true: 0.99
        prob_given_false: 0.05
        platform: state
        to_state: "home"

      - entity_id: person.spouse
        prob_given_true: 0.99
        prob_given_false: 0.05
        platform: state
        to_state: "home"

      # Recent motion
      - entity_id: binary_sensor.living_room_motion
        prob_given_true: 0.7
        prob_given_false: 0.1
        platform: state
        to_state: "on"

      # Front door opened recently (template sensor)
      - entity_id: binary_sensor.front_door_recent
        prob_given_true: 0.8
        prob_given_false: 0.3
        platform: state
        to_state: "on"

Supporting Templates

template:
  - binary_sensor:
      - name: "Front Door Recent"
        state: >
          {{ (now() - states.binary_sensor.front_door.last_changed).seconds < 600 }}

      - name: "Any Motion Recent"
        state: >
          {% set sensors = [
            'binary_sensor.living_room_motion',
            'binary_sensor.kitchen_motion',
            'binary_sensor.bedroom_motion'
          ] %}
          {% set ns = namespace(recent=false) %}
          {% for sensor in sensors %}
            {% if (now() - states[sensor].last_changed).seconds < 1800 %}
              {% set ns.recent = true %}
            {% endif %}
          {% endfor %}
          {{ ns.recent }}

Room-Level Presence

For per-room presence, mmWave sensors outperform PIR:

# ESPHome mmWave sensor config
binary_sensor:
  - platform: ld2410
    has_target:
      name: "Office Presence"
    has_moving_target:
      name: "Office Motion"
    has_still_target:
      name: "Office Stationary"

Room Occupancy Entity

template:
  - binary_sensor:
      - name: "Office Occupied"
        state: >
          {{ is_state('binary_sensor.office_presence', 'on')
             or is_state('binary_sensor.office_motion', 'on')
             or (is_state('binary_sensor.office_door', 'off')
                 and was_state('binary_sensor.office_presence', 'on', 300)) }}
        delay_off: "00:05:00"

The logic:

  1. Sensor detects presence → occupied
  2. Motion detected → occupied
  3. Door closed AND was recently occupied → probably still occupied
  4. 5-minute delay before marking unoccupied

Arrival and Departure Automations

Smart Arrival

automation:
  - alias: "Welcome Home"
    trigger:
      - platform: state
        entity_id: binary_sensor.someone_home
        from: "off"
        to: "on"
    condition:
      - condition: time
        after: "06:00:00"
        before: "22:00:00"
    action:
      - service: light.turn_on
        target:
          area_id: entryway
        data:
          brightness_pct: 80
      - service: climate.set_temperature
        target:
          entity_id: climate.main_floor
        data:
          temperature: 72
      - service: media_player.play_media
        target:
          entity_id: media_player.kitchen_speaker
        data:
          media_content_id: "media-source://tts/welcome_home"
          media_content_type: "provider"

Confident Departure

The tricky part—you don’t want lights turning off while you’re in the shower.

automation:
  - alias: "House Empty - Away Mode"
    trigger:
      - platform: state
        entity_id: binary_sensor.someone_home
        from: "on"
        to: "off"
        for: "00:10:00"  # 10 minute buffer
    condition:
      # Double-check with motion sensors
      - condition: state
        entity_id: binary_sensor.any_motion_recent
        state: "off"
    action:
      - service: climate.set_preset_mode
        target:
          entity_id: climate.main_floor
        data:
          preset_mode: "away"
      - service: light.turn_off
        target:
          entity_id: all
      - service: lock.lock
        target:
          entity_id: lock.front_door

Guest Handling

Guests don’t have the app. Handle them with motion-based overrides:

input_boolean:
  guest_mode:
    name: "Guest Mode"
    icon: mdi:account-group

automation:
  - alias: "Detect Guests"
    trigger:
      - platform: state
        entity_id: binary_sensor.any_motion_recent
        to: "on"
    condition:
      - condition: state
        entity_id: binary_sensor.someone_home
        state: "off"
      - condition: state
        entity_id: input_boolean.guest_mode
        state: "off"
    action:
      - service: notify.mobile_app_charles_phone
        data:
          title: "Motion Detected"
          message: "Motion detected but no one marked home. Guest?"
          data:
            actions:
              - action: "ENABLE_GUEST_MODE"
                title: "Enable Guest Mode"
              - action: "FALSE_ALARM"
                title: "False Alarm"

Debugging Presence Issues

When presence detection misbehaves:

Check Sensor States

# Add to dashboard
type: entities
title: Presence Debug
entities:
  - entity: person.charles
  - entity: device_tracker.charles_phone_app
  - entity: device_tracker.charles_phone_wifi
  - entity: binary_sensor.someone_home
  - entity: binary_sensor.any_motion_recent

Trace Bayesian Sensor

# Enable debug logging temporarily
logger:
  default: warning
  logs:
    homeassistant.components.bayesian: debug

Common Issues

  1. Phone tracker shows “unknown” — App background refresh disabled
  2. Slow departure detection — Router integration has long timeout
  3. False arrivals — GPS drift near home zone boundary
  4. Motion sensor stuck — PIR sensitivity too high

Performance Results

After implementing sensor fusion:

MetricSingle SensorSensor Fusion
False departures/week5-100-1
False arrivals/week3-50
Detection latency30-120s5-15s
Guest handlingManualSemi-automatic

The difference is dramatic. Automations that were frustrating (lights turning off mid-movie) became invisible and reliable.

Key Takeaways

  1. Never trust a single sensor — All sensors fail, fuse multiple sources
  2. Bayesian beats boolean — Probability handles uncertainty gracefully
  3. Room presence needs mmWave — PIR misses stationary occupants
  4. Add buffers to departure — Fast departure detection causes pain
  5. Plan for guests — Not everyone will have your app

Reliable presence detection transforms home automation from gimmick to genuine quality-of-life improvement. The setup takes effort, but the result is a home that actually understands when you’re there.

Enjoyed this post?

Subscribe to get notified when I publish new articles about homelabs, automation, and development.

No spam, unsubscribe anytime. Typically 2-4 emails per month.

Related Posts