Nuki Card with Callback support (supports both Lock & Opener, it replaces the official integration)

That’s what I suspected. We gave for granted you were using my integration, because you’re writing in this thread, but I had the feeling that was not the case.

This integration was made exactly for the problem you are seeing: the official integration is based on polling, so you have to wait for the polling timer to expire before seeing a status update. That is your problem. You have the solution, but it’s up to you to decide using it or not. Next time please specify that you are NOT using this integration but you are looking for help for the official integration. :slight_smile:

I don’t know the answer to this because I never had the need. But I’m pretty confident that if you use this integration and not the official one, the benefits will let you reconsider the need.

You could add an instant notification via telegram (or other platform) when you action the lock/unlock.

Ciao,

Alessandro

With your integration my automation (turning on the green led indicator) now is faster. :slight_smile:

What a surprise. :slight_smile:

Jokes apart, how long does it take now? It should be maximum 10secs, but I suspect something around 8. Let me know, I’m curious.

Hi! I have continuous errors in the log I did the procedure from 0 to three times … but I keep having problems … do you want and time to help me understand?

HI, it would help when you post your errors from the logfile.

Ciao,

you ask for help since a long time, but you never post your config files, your logs, etc.

How can we help you, by reading your mind? Use the forum like others: posting all needed information to help us help you.

Problems won’t be solved just by asking for help, you need to do what’s necessary to be helped.

Forza e coraggio…se leggi più su, c’era un’altro utente con i tuoi stessi problemi, è bastato fargli rifare la configurazione con calma e tranquillità.

It is 10 sec now (but I have NUKI bridge hardware release 1 - maybe the rel. 2 is even faster).
If I now remove the official NUKI integration and use your solution only, locking and unlocking should be done with API-call right?

Grazie per l’aiuto!

1 Like

Both official Nuki integration and alexdelprete’s integration use API call to lock/unlock. The difference come from the way to get state values (callback vs polling), and also the number of properties retrieved (much more with alexdelprete’s integration).

maybe the rel. 2 is even faster

I have the rel.2 and it takes up to 13" from to push the button into HA mobile UI app until the lock is updated into HA mobile app UI. I can see it takes a few seconds after the lock/unlock operation is completed on the lock to see the card… and the Nuki app updated (even with the mobile near the lock so Bluetooth is ok). :face_with_raised_eyebrow:

This is My log problem

Seems you are using the official nuki integration.
This thread is about another a different integration coded by Alex.

I tried with telepathy, but I’m having weird problems, need to work on it…:slight_smile:

The official integration uses the bridge like I do, but it does it via polling.

All commands of this integration are based on the Bridge API 1.12. You can see the code yourself, you installed it yesterday.

Here’s the lock/unlock actions, made through one single REST parametrised command:

nuki_lock_action:
  url: "http://{{ states('sensor.nuki_bridge_host') }}:{{ states('sensor.nuki_bridge_port') }}/lockAction?nukiId={{ states('sensor.nuki_id') }}&token={{ states('sensor.nuki_bridge_token') }}&action={{ action }}"

That command is being used by the lock switch, you can see the code here:

- platform: template
  name: "Nuki Lock Action"
  value_template: "{{ is_state_attr('binary_sensor.nuki_door_state', 'lock_state', 'locked') }}"
  availability_template: "{{ state_attr('binary_sensor.nuki_door_state', 'lock_state') != None }}"
  lock:
    service: rest_command.nuki_lock_action
    data:
      action: 2
  unlock:
    service: rest_command.nuki_lock_action
    data:
      action: 1

The core of the integration is the Template Trigger sensor, which receives the callback by the bridge and immediately updates the status of the sensors, door sensor included. Then there are 2 additional REST sensors that use polling, mainly to retrieve status/data from all the additional sensors I included. The triggered sensor gets updated ALSO by these two polling REST sensors.

sensor:
  - platform: rest
    scan_interval: 300
    resource_template: "http://{{ states('sensor.nuki_bridge_host') }}:{{ states('sensor.nuki_bridge_port') }}/list?&token={{ states('sensor.nuki_bridge_token') }}"
    name: "Nuki Endpoint List"
    value_template: "OK"
    json_attributes:
      - lastKnownState
      - firmwareVersion
      - nukiId
      - name

  - platform: rest
    scan_interval: 300
    resource_template: "http://{{ states('sensor.nuki_bridge_host') }}:{{ states('sensor.nuki_bridge_port') }}/info?&token={{ states('sensor.nuki_bridge_token') }}"
    name: "Nuki Endpoint Info"
    value_template: "OK"
    json_attributes:
      - versions
      - scanResults
      - wlanConnected
      - serverConnected

So you have the best of both worlds: a Nuki integration with all relevant info of the system (if needed), and the quick updates through callbacks.

Probably the official integration will do something like this in the future, but we don’t know when that’ll happen, and I didn’t feel to wait any longer.

Hope it answers your questions. :slight_smile:

Alessandro

What a mess. I see errors related to official integration, not this integration. This means you have communication problems with the bridge, also with the official integration.

You need to fix the basics first (WiFi or other problems) then you can make this or the official integration work.

Open a shell and show me the output of this command:

Windows: ping -t bridge_ip
Linux: ping bridge_ip

It’s a simple ping command, it runs forever, you break with ctrl-c, let it run for 5 secs and then show me the output with a screenshot.

Last thing, a question: does the OFFICIAL integration work?

5 Ping every 5 seconds for 1 hour

My wifi network works well, and the signal comes “strong” and constant

Official integration (for use) appears to work

PS: I’ll leave the active Ping for a while anyway

These are errors of the official integration: it can’t connect properly to the bridge. If you don’t solve this issue, neither the official nor this integration will work because they both rely on proper communication with the bridge.

image image

v5.1 released. Check first post.

1 Like

Hi Axel,

The type wasn’t necessary, so I removed it and updated my Dahua open door automation with your suggestion, thnx.

I’ve also been playing around with your code and have manged to put everything into one file so that you can use it as a package. It was a bit hard while templates aren’t supported in a package, but I have worked around it using an input_boolean and an automation and also added unique_id’s where possible so that these entities can be changed in the UI when needed:

#######################################################################################################################
###                                                                                                                 ###
### Automations                                                                                                     ###
###                                                                                                                 ###
### REMARK: The automation needs a "webhook_id". This has to be inserted manually. The "webhook_id" is a long-term  ###
###         token that can be generated in the HA profiles page.                                                    ###
###                                                                                                                 ###
#######################################################################################################################

automation:
  - id: '1625220770936'
    alias: Nuki
    description: Automation for the Nuki doorlock
    trigger:
      - platform: webhook
        webhook_id: >-
          ### ==> Replace this line with your own webhook <== ###
      - platform: event
        event_type: event_template_reloaded
      - platform: state
        entity_id: sensor.nuki_door_sensor_state
        to: open
      - platform: state
        entity_id: sensor.nuki_door_sensor_state
        to: closed
      - platform: homeassistant
        event: start
    condition: []
    action:
      - service: homeassistant.update_entity
        target:
          entity_id:
            - sensor.nuki_endpoint_list
            - sensor.nuki_endpoint_info
      - choose:
          - conditions:
              - condition: template
                value_template: >-
                  {{ state_attr('sensor.nuki_endpoint_list',
                  'lastKnownState')['stateName'] == "locked" }}
            sequence:
              - service: input_boolean.turn_off
                target:
                  entity_id: input_boolean.nuki_ib_door_sensor
          - conditions:
              - condition: template
                value_template: >-
                  {{ state_attr('sensor.nuki_endpoint_list',
                  'lastKnownState')['stateName'] == "unlocked" }}
            sequence:
              - service: input_boolean.turn_on
                target:
                  entity_id: input_boolean.nuki_ib_door_sensor
        default: []
    mode: single

#######################################################################################################################
###                                                                                                                 ###
### Binary sensors                                                                                                  ###
###                                                                                                                 ###
#######################################################################################################################

binary_sensor:
  - platform: template
    sensors:
      nuki_door_state:
        unique_id: nuki_door_state
        friendly_name: "Nuki Door State"
        device_class: door
        value_template: >
          {{ states('input_boolean.nuki_ib_door_sensor') }}
        availability_template: >
          {{ (is_state('sensor.nuki_door_sensor_state', 'open') or is_state('sensor.nuki_door_sensor_state', 'closed')) }}
        icon_template: >
          {% set trigdoor = states('sensor.nuki_door_sensor_state') %}
          {% set triglock = states('sensor.nuki_lock_sensor_state') %}
          {% if (trigdoor == 'open') %}
            mdi:door-open
          {% elif trigdoor == 'closed' and triglock == 'locked' %}
            mdi:door-closed-lock
          {% elif trigdoor == 'closed' and triglock == 'unlocked' %}
            mdi:door-closed
          {% else %}
            mdi:alert-box-outline
          {% endif %}
        attribute_templates:
          nuki_id: >
            {{ states('sensor.nuki_id') }}
          door_state: >
            {% set my_state = {1: 'deactivated', 2: 'closed', 3: 'open', 4: 'unknown', 5: 'calibrating'} %}
            {{ states('sensor.nuki_door_sensor_state') }}
          lock_state: >
            {% set my_state = {0: 'uncalibrated', 1: 'locked', 2:'unlocking', 3: 'unlocked', 4: 'locking', 5: 'unlatched', 6: "unlocked (lock ‘n’ go)", 7: 'unlatching', 254: 'motor blocked', 255: 'undefined'} %}          
            {{ states('sensor.nuki_lock_sensor_state') }}
          lock_battery: >
            {{ states('sensor.nuki_lock_battery_level') }}
          lock_battery_critical: >
            {{ states('sensor.nuki_lock_battery_critical_state') }}
          keypad_battery_critical: >
            {% if states('sensor.nuki_keypad_battery_critical_state') != 'unknown' %}
              {{ states('sensor.nuki_keypad_battery_critical_state') }}
            {% else %}
              not installed 
            {% endif %}
          last_update: "{{ strptime(as_timestamp(now()) | timestamp_local, '%Y%m%d %H:%M:%S') }}"
          door_sensor_polled: "{{ states('sensor.nuki_door_sensor_state') }}"
          lock_sensor_polled: "{{ states('sensor.nuki_lock_sensor_state') }}"

#######################################################################################################################
###                                                                                                                 ###
### Input booleans                                                                                                  ###
###                                                                                                                 ###
#######################################################################################################################

input_boolean:
  nuki_ib_door_sensor:
    name: Nuki Door Sensor
    icon: mdi:door-open

#######################################################################################################################
###                                                                                                                 ###
### Locks                                                                                                           ###
###                                                                                                                 ###
#######################################################################################################################

lock:
  - platform: template
    name: "Nuki Lock Action"
    unique_id: nuki_lock_action
    value_template: "{{ is_state_attr('binary_sensor.nuki_door_state', 'lock_state', 'locked') }}"
    availability_template: "{{ state_attr('binary_sensor.nuki_door_state', 'lock_state') != None }}"
    lock:
      service: rest_command.nuki_lock_action
      data:
        action: 2
    unlock:
      service: rest_command.nuki_lock_action
      data:
        action: 1

#######################################################################################################################
###                                                                                                                 ###
### rest commands                                                                                                   ###
###                                                                                                                 ###
#######################################################################################################################

rest_command:
  nuki_lock_action:
    url: "http://{{ states('sensor.nuki_bridge_host') }}:{{ states('sensor.nuki_bridge_port') }}/lockAction?nukiId={{ states('sensor.nuki_id') }}&token={{ states('sensor.nuki_bridge_token') }}&action={{ action }}"
    content_type: "application/json"

#######################################################################################################################
###                                                                                                                 ###
### sensors                                                                                                         ###
###                                                                                                                 ###
#######################################################################################################################

sensor:
  - platform: rest
    scan_interval: 300
    resource_template: "http://{{ states('sensor.nuki_bridge_host') }}:{{ states('sensor.nuki_bridge_port') }}/list?&token={{ states('sensor.nuki_bridge_token') }}"
    name: "Nuki Endpoint List"
    value_template: "OK"
    json_attributes:
      - lastKnownState
      - firmwareVersion
      - nukiId
      - name

  - platform: rest
    scan_interval: 300
    resource_template: "http://{{ states('sensor.nuki_bridge_host') }}:{{ states('sensor.nuki_bridge_port') }}/info?&token={{ states('sensor.nuki_bridge_token') }}"
    name: "Nuki Endpoint Info"
    value_template: "OK"
    json_attributes:
      - versions
      - scanResults
      - wlanConnected
      - serverConnected

  - platform: template
    sensors:
      nuki_bridge_host:
        unique_id: nuki_bridge_host
        friendly_name: "Nuki Bridge Host"
        value_template: !secret nuki_bridge_host
      
  - platform: template
    sensors:
      nuki_bridge_port:
        unique_id: nuki_bridge_port
        friendly_name: "Nuki Bridge Port"
        value_template: !secret nuki_bridge_port

  - platform: template
    sensors:
      nuki_bridge_token:
        unique_id: nuki_bridge_token
        friendly_name: "Nuki Bridge Token"
        value_template: !secret nuki_bridge_token

  - platform: template
    sensors:
      nuki_device_name:
        unique_id: nuki_device_name
        friendly_name: "Nuki Device Name"
        icon_template: mdi:alphabetical-variant
        value_template: >
          {% if states('sensor.nuki_endpoint_info') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_info','scanResults')[0]['name'] }}
          {% endif %}

  - platform: template
    sensors:
      nuki_bridge_fw_version:
        unique_id: nuki_bridge_fw_version
        friendly_name: "Nuki Bridge FW Version"
        icon_template: mdi:numeric
        value_template: >
          {% if states('sensor.nuki_endpoint_info') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_info','versions')['firmwareVersion'] }}
          {% endif %}

  - platform: template
    sensors:
      nuki_bridge_lock_bt_rssi:
        unique_id: nuki_bridge_lock_bt_rssi
        friendly_name: "Nuki Bridge<->Lock BT RSSI"
        icon_template: mdi:signal-distance-variant
        value_template: >
          {% if states('sensor.nuki_endpoint_info') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_info','scanResults')[0]['rssi'] }}
          {% endif %}

  - platform: template
    sensors:
      nuki_bridge_wifi_connected:
        unique_id: nuki_bridge_wifi_connected
        friendly_name: "Nuki Bridge WiFi Connected"
        icon_template: mdi:wifi-cog
        value_template: >
          {% if states('sensor.nuki_endpoint_info') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_info','wlanConnected') }}
          {% endif %}

  - platform: template
    sensors:
      nuki_bridge_wifi_fw_version:
        unique_id: nuki_bridge_wifi_fw_version
        friendly_name: "Nuki Bridge WiFi FW Version"
        icon_template: mdi:numeric
        value_template: >
          {% if states('sensor.nuki_endpoint_info') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_info','versions')['wifiFirmwareVersion'] }}
          {% endif %}

  - platform: template
    sensors:
      nuki_bridge_cloud_connected:
        unique_id: nuki_bridge_cloud_connected
        friendly_name: "Nuki Bridge Cloud Connected"
        icon_template: mdi:server-network
        value_template: >
          {% if states('sensor.nuki_endpoint_info') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_info','serverConnected') }}
          {% endif %}
 
  - platform: template
    sensors:
      nuki_bridge_lock_bt_state:
        unique_id: nuki_bridge_lock_bt_state
        friendly_name: "Nuki Bridge<->Lock BT State"
        icon_template: >
          {% if states('sensor.nuki_endpoint_info') == "OK" %}
            {% if state_attr('sensor.nuki_endpoint_info','scanResults')[0]['paired'] %}
              mdi:bluetooth-connect
            {% elif not state_attr('sensor.nuki_endpoint_info','scanResults')[0]['paired'] %}
              mdi:bluetooth-off
            {% else %}
              mdi:bluetooth-audio
            {% endif %}
          {% endif %}
        value_template: >
          {% if states('sensor.nuki_endpoint_info') == "OK" %}
            {% if state_attr('sensor.nuki_endpoint_info','scanResults')[0]['paired'] %}
              connected
            {% elif not state_attr('sensor.nuki_endpoint_info','scanResults')[0]['paired'] %}
              disconnected
            {% else %}
              Unknown
            {% endif %}
          {% endif %}

  - platform: template
    sensors:
      nuki_id:
        unique_id: nuki_id
        friendly_name: "Nuki ID"
        icon_template: mdi:numeric
        value_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_list','nukiId') }}
          {% endif %}

  - platform: template
    sensors:
      nuki_lock_fw_version:
        unique_id: nuki_lock_fw_version
        friendly_name: "Nuki Lock FW Version"
        icon_template: mdi:numeric
        value_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_list','firmwareVersion') }}
          {% endif %}

  - platform: template
    sensors:
      nuki_lock_battery_critical_state:
        unique_id: nuki_lock_battery_critical_state
        friendly_name: "Nuki Lock Battery Critical State"
        icon_template: mdi:battery-alert-variant-outline
        value_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['batteryCritical'] }}
          {% endif %}

  - platform: template
    sensors:
      nuki_friendly_name:
        unique_id: nuki_friendly_name
        friendly_name: "Nuki Friendly Name"
        icon_template: mdi:numeric
        value_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {{ state_attr('sensor.nuki_endpoint_list','name') }}
          {% endif %}

  - platform: template
    sensors:
      nuki_last_activity:
        unique_id: nuki_last_activity
        friendly_name: "Nuki Last Activity"
        icon_template: mdi:clock-check-outline
        value_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {{ (as_timestamp(state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['timestamp'])) | timestamp_custom("%H:%M (%b %d)") }}
          {% endif %}  

  - platform: template
    sensors:
      nuki_lock_battery_level:
        unique_id: nuki_lock_battery_level
        friendly_name: "Nuki Lock Battery Level"
        device_class: "battery"
        unit_of_measurement: "%"
        icon_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {% set battery_level = state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['batteryChargeState'] | default(0) | int %}
            {% set battery_charging = state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['batteryCharging'] %}
            {% set battery_round = (battery_level / 10) | int * 10 %}
            {% if battery_round >= 100 and not battery_charging %}
              mdi:battery
            {% elif battery_round >= 100 and battery_charging %}
              mdi:battery-charging
            {% elif battery_round > 0 and not battery_charging %}
              mdi:battery-{{ battery_round }}
            {% elif battery_round > 0 and battery_charging %}
              mdi:battery-charging-{{ battery_round }}
            {% else %}
              mdi:battery-alert-variant-outline
            {% endif %}
          {% endif %}
        value_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {% set battery_level = state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['batteryChargeState'] | default(0) | int %}
            {% if state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['batteryCharging'] %}
              {{ battery_level }}
            {% else %}
              {{ battery_level }}
            {% endif %}
          {% endif %}

  - platform: template
    sensors:
      nuki_door_sensor_state:
        unique_id: nuki_door_sensor_state
        friendly_name: "Nuki Door Sensor State"
        icon_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {% set door_icon = state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['doorsensorState'] %}
            {% set lock_icon = state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['state'] %}
            {% if door_icon == 2 and lock_icon == 3 %}
              mdi:door-closed
            {% elif door_icon == 2 and lock_icon == 1 %}
              mdi:door-closed-lock
            {% elif door_icon == 3 %}
              mdi:door-open
            {% endif %}
          {% endif %}
        value_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {% set my_state = {1: 'deactivated', 2: 'closed', 3: 'open', 4: 'unknown', 5: 'calibrating'} %}
            {{ my_state[state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['doorsensorState']] }}
          {% endif %}

  - platform: template
    sensors:
      nuki_lock_sensor_state:
        unique_id: nuki_lock_sensor_state
        friendly_name: "Nuki Lock Sensor State"
        icon_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {% set lock_icon = state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['state'] %}
            {% if lock_icon == 1 %}
              mdi:lock-outline
            {% elif lock_icon == 3 %}
              mdi:lock-open-outline
            {% endif %}
          {% endif %}
        value_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {% set my_state = {0: 'uncalibrated', 1: 'locked', 2:'unlocking', 3: 'unlocked', 4: 'locking', 5: 'unlatched', 6: "unlocked (lock ‘n’ go)", 7: 'unlatching', 254: 'motor blocked', 255: 'undefined'} %}
            {{ my_state[state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['state']] | default('loading...') }}
          {% endif %}

  - platform: template
    sensors:
      nuki_keypad_battery_critical_state:
        unique_id: nuki_keypad_battery_critical_state
        friendly_name: "Nuki Keypad Battery Critical State"
        icon_template: mdi:battery-alert-variant-outline
        availability_template: >
          "{{ state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['keypadBatteryCritical'] != null }}"
        value_template: >
          {% if states('sensor.nuki_endpoint_list') == "OK" %}
            {% if state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['keypadBatteryCritical'] != null %}
              {{ state_attr('sensor.nuki_endpoint_list', 'lastKnownState')['keypadBatteryCritical'] }}
            {% else %}
              not installed 
            {% endif %}
          {% endif %}


The only thing you have to do now is create a directory “packages” in your homeassistant directory and add in your configuration.yaml:

homeassistant:
  packages: !include_dir_named packages/

Please feel free to try and to use.

Best regards,

Jeroen

PS: My code is still based on the 5.0 version…

Hi Jeroen,

you made a good job, thanks for sharing it. The problem is that you are using the old syntax for sensors etc. and I wanted to release a package using the new recommended syntax, because I feel the old one will probably not work in the future.

When I tried to put everything in one file, with the new syntax, there was an error on the trigger sensors that are not supported in packages, that’s why I had to stop with my idea to release a package. :slight_smile:

But you know what? Let’s release the package with the old syntax, then, when they will resolve the issue of the new syntax for the template trigger sensor in packages, we’ll release the updated version of the package.

What do you think of this? Obviously I will credit you for creating the packaged version when I publish it. Let me know your thoughts first.

Thanks again for you contribution, I deeply appreciate it.

Question for you @spokin: for the token and the bridge host, etc. you are using the sensors I built from the secrets.yaml, but not for the webhook. Why don’t we use the same logic so the user doesn’t have to manually input anything in the package file? I’ll rework the package file to see if it’s doable. :slight_smile:

I will also follow the suggestion @kongo09 made regarding the secrets in the sensor, using an alternative input_text. Let’s see how it works out…

@spokin, another idea: could a blueprint be made out of the packaged version? So we could automate the installation asking for inputs (token, webhook, etc.) to the user…so we could automate both the installation and the configuration.