technyon / nuki_hub

Use an ESP32 as a Hub between a NUKI Lock and your smarthome.
MIT License
508 stars 39 forks source link

Feature request: Auto discovery for presence detected devices in Home Assistant #159

Closed bcutter closed 1 year ago

bcutter commented 1 year ago

The ability of doing presence detection with NUKI Hub is a quite powerful feature.

Unfortunately it is not very well known (but stated in the docs ✅).

And most important: having that information in MQTT currently is the "end of the road" for most normal users (not being into templating that much or at all) resulting in not using that "free lunch information" at all.


FR:

1) Add a config option "publish Bluetooth presence devices to Home Assistant" 2) Enable auto discovery for presence detected devices, so for every device a device_tracker.abc entity is automatically created and updated if the state changes. 3) We probably need a logic and config option like "presence timeout": after XX seconds devices not discovered anymore are set from "home" to "not_home".


That would make NUKI hub such a powerful Bluetooth device tracker and be probably one of THE best add-on features.

ralle12345 commented 1 year ago

I would like to add that if would be useful to also publish the rssi of the received beacon per presence device

thor9898 commented 1 year ago

is this some kind of ESPresense?

technyon commented 1 year ago

This feature is out of scope for NUKI Hub. Let me explain

Since ESPs are inexpensive, I suggest to use another ESP for presence tracking.

@ralle12345 The rssi value per device is available, you can read it from the published CSV data.

bcutter commented 1 year ago

As the information is there, one should do something with it. Following the basically completely understandable "not in core focus of this project" approach, otherwise one could ask why it exists at all.

If one has ideas / working snippets on how to create and update device_tracker entities in Home Assistant based on the currently available MQTT topics please let us (me) know.

mundschenk-at commented 1 year ago

@bcutter You do not really want to add a device_tracker for every BLE beacon picked up by the Nuki Hub, as this would add a tracker for every MiFlora sensor and Philips Hue bulb in range of the hub (as well as for the lock itself!).

bcutter commented 1 year ago

Indeed I want to monitor only specific Bluetooth devices. Underlying main task remains the same: use MQTT data to create and update device tracker entity.

If there's another project exactly doing this (I think there is in the big ESP world)... feel free to share some links 😃

mundschenk-at commented 1 year ago

https://espresense.com

technyon commented 1 year ago

The reason this exists is that it is a by-product of something that needs to be done anyway: scanning for beacons. This is necessary for 1. pairing the lock and 2. detecting lock state changes. The information about beacons is always collected, wether presence detection is enabled or not. If enabled, it's just packed into a CSV payload and published. That's easy. And parsing data from CSV is possible, just less convenient.

Making a UI to allow to configure which beacons to track, then dynamically publishing discovery topics, deleting them when necessary and so on adds a layer of complexity that's time-consuming to implement. And it doesn't stop at implementation. features need to be tested before release and if changes are made to the code. After release, it'll need maintenance (e. g. reported bugs that need to be fixed and so on). Considering there's already a firmware that takes care all of this and does it well, I think it's better to just that firmware on a secondary ESP.

bcutter commented 1 year ago

I understand Nuki Hub won't provide anything besideds the raw presence detection data. It would be great to get some kickstart assistance on how to realize this on a "for one device only" basis.

So: Can someone help on how to create some kind of template sensor for one specific bluetooth device out of the presence topic?

Target: create a sensor which contains the connection strength of a certain bluetooth device nearby one SL/Nuki Hub (the /nuki_smartlock/presence/devices topic contains bluetooth devices discovered by the Nuki Hub, not the SL, right?). Sensor value should contain the connection strength if available or show 'unavailable' or '0' in case the device is not discovered.

Example input (one line/entry of the presence/devices topic): XX:XX:XX:XX:XX:XX;Device name;-62

In the end I want to use the sensor in an automation (Home Assistant) as trigger/condition (like "once state sensor.device_name >= -50, do something").

mundschenk-at commented 1 year ago

Not tested, but something like

mqtt:
  sensor:
    - name: "<device name>"
      unique_id: '<uuid>'
      state_topic: "<nuki topic>/presence/devices"
      value_template: >
         {%- for line in value.split('\n') -%}
              {%- if line[:17] == 'XX:XX:XX:XX:XX:XX' -%}
                 {{ line[-3:] }}
              {%- endif -%}
         {%- endfor -%}
      device:
        identifiers: nuki_<device>

However, this question would be more suitable to https://community.home-assistant.io/, as it is not really specific to Nuki Hub.

bcutter commented 1 year ago

@mundschenk-at Indeed the forum is better. It's just that your piece is working, except being unable to set a "default" state if the stuff in the for loop does not apply.

Even this is great for starting, after now more than 30 minutes I was unable to modify it to just show "home" once a certain MAC is discovered and show "not_home" if it is not. So it's a pretty pain in the a** unfortunately.

Doing all this manually would be so much easier if presence information would not be provided as a flat list/array but a dedicated sub-topic for each discovered device, by the way.

This is my latest approach:

      value_template: >
        {% set online = 'false' %}
        {%- for line in value.split('\n') -%}
          {%- if line[:17] == 'XX:XX...' -%}
            {% set online = 'true' %}
          {%- endif -%}
        {%- endfor -%}
        {%- if online == 'true' -%}
          home
        {%- else -%}
          not_home
        {%- endif -%}

Unfortunately it always gives not_home even it should be home. Maybe the {% set online = 'true' %} is not working outside the for loop? Damn that scripting stuff, really. I hate it :-D


After trying for almost 1 more hour I tend to really quit this shit. Presence detection in NUKI Hub is useless unless you're a scripting pro. Currently one needs to 1) Exfiltrate the presence status for a single Bluetooth device from the Nuki Hub topic (I'm failing here) 2) Convert the output (sensor) of step 1 to an actual device_tracker using either device_tracker.see service or MQTT Device Tracker integration which both are not very handy. Potentially using the MQTT Device Tracker integration would allow to skip step 1 in case one manages to convert the complex value_template to this device_tracker entity definition. I don't get it.


In the end I just wanted to monitor one specific device with the free information from Nuki Hub. Desired output: device_tracker.device_discovered_by_nuki_hub with home and not_home states.

I think if I would have spent the last 1,5 hours for deep-diving into ESPresense (https://espresense.com), I would be much closer to that target already.

madface303 commented 9 months ago

I know this is not the home assistant forum, but maybe it would help the one or other. Just create a mqtt sensor:

mqtt:
  sensor:
    - name: "nuki_presence_sensor"
      state_topic: "nuki/presence/devices"
      value_template: "{{ 'home' if 'YOUR-iBEACON-ID' in value else 'not_home' }}"
      unique_id: "nuki/presence/devices_uid"

Then you have a sensor if your iBeacon ID is recognized by NukiHUB, home if recognized and not_home if you are away.

xaris33 commented 9 months ago

I know this is not the home assistant forum, but maybe it would help the one or other. Just create a mqtt sensor:

mqtt:
  sensor:
    - name: "nuki_presence_sensor"
      state_topic: "nuki/presence/devices"
      value_template: "{{ 'home' if 'YOUR-iBEACON-ID' in value else 'not_home' }}"
      unique_id: "nuki/presence/devices_uid"

Then you have a sensor if your iBeacon ID is recognized by NukiHUB, home if recognized and not_home if you are away.

Thank you, this works great.

Any idea how we could extract the rssi as well to a sensor?

madface303 commented 9 months ago

Sure, here you only use value instead of the if clause:

mqtt:
  sensor:
    - name: "nuki_esp32_lock_rssi"
      state_topic: "nuki/lock/rssi"
      value_template: "{{ value }}"
      unique_id: nuki_esp32_nuki_lock_rssi_unique_id

I have doubled these 2 in the home assistant forum, if there are further questions we should continue there

https://community.home-assistant.io/t/nuki-hub-firmware-for-the-esp32/417572/301

bcutter commented 8 months ago

I know this is not the home assistant forum, but maybe it would help the one or other. Just create a mqtt sensor:

mqtt:
  sensor:
    - name: "nuki_presence_sensor"
      state_topic: "nuki/presence/devices"
      value_template: "{{ 'home' if 'YOUR-iBEACON-ID' in value else 'not_home' }}"
      unique_id: "nuki/presence/devices_uid"

Then you have a sensor if your iBeacon ID is recognized by NukiHUB, home if recognized and not_home if you are away.

Totally off-topic, but potentially helpful: (@madface303: maybe you can link the I have doubled these 2 in the home assistant forum [...] please?)

Next to good behavior of using at least source_type: bluetooth (edit: only possible for MQTT device trackers, not MQTT sensors) I have to summarize: Thank you (not tested, but https://github.com/technyon/nuki_hub/issues/159#issuecomment-1554358294 was not working). But unfortunately that's still only the half of the way. Because: In the end I need a device_tracker entity.

That's where probably https://github.com/pnbruckner/ha-composite-tracker will enter the room. ...as it supports using the UI which outperforms the native mqtt option (https://www.home-assistant.io/integrations/device_tracker.mqtt/#yaml-configuration).

I'll

xaris33 commented 8 months ago

I'm not sure I understand what you are trying to do, but I have been using the beacon id matching code in an automation for a while now and it works great. I switch on the transmitter when the device enters the home zone, open the door when the matching occurs (adjusting the transmitter power has made this spot-on for 99% of the time, door opens pretty much consistently as I'm 1-2 steps away), switch off the transmitter. As I have multiple users I switch off all other transmitters as well here (and reset their automations) to prevent multiple unlocks when arriving at the same time.

This works a lot better than the native auto unlock, which would take 5-10-15 seconds of waiting to open the door.

A bit hacky but it works so well I haven't felt the need to tweak it.

bcutter commented 8 months ago

I don't want to use a sensor.device but a device_tracker.device, that's the only thing. Of course, just for an automation the sensor.device works fine too. But sensors are not for tracking devices, they don't support source_type etc.. If one really wants to to device tracking and append a bluetooth device tracker to a person, a simple sensor.device is not sufficient.