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

Correct. That’s why, even if stylistically I prefer the other version, this is way much easier to maintain and support. Less errors for non-expert users, less problems in this thread. :slight_smile:

Suddenly the bridge seems to refuse connections from HA:


If I paste the URL in my browser, I get all the info. Is it possible that the bridge blocks IPs for example if requests are made too frequently?

Nope. Check connectivity from HA, do you have SSH access to HA? You can try curl from there first.

Is the bridge in a separate VLAN? Is there a firewall or router between HA and the bridge?

Did you restart the bridge? If it’s not enough, restart HA+Bridge. Basic troubleshooting first.

Had some issues with door state and lock action entitites

Just upgraded to 2021.7.1 see what’s going on now.

Can’t understand the language. :slight_smile:

What’s going on? I upgraded to 7.1 (and all the intermediate betas too), didn’t notice issues.

Leanguage does not metter take a look at right part of entity visual state - grey color means unavailable. For over 5 hrs when I was away so no one at home it started to disconnect/connect for nor reason.

Language matters, always. Someone could be color-blinded…

So there was a disconnection issue from HA and the bridge…there could be tons of reasons, maybe if you provide some logs, check the wifi, etc. we could better understand what happened.

Nuki Card only does http calls, it’s not rocket science, if the sensors went unavailable it means that the bridge didn’t answer or couldn’t be reached.

Let me gather info for you. Just a side note - AP is in same room that Bridge is so well 3-4 m away, then Bridge istelf is 2-3 away from Nuki Lock so it’s wierd, no one was at home at that time, firmware is upgraded and I had no issues on 0.6b1.

The code has no issues that could create that situation. The bridge was not responding, you have to find out why. I bet on wifi. If the world was built on ethernet, you wouldn’t see these “weird” issues. :slight_smile:

Obviously, I recommend an analysis of the logs first: HA logs, AP logs, etc. something was stopping the communication between HA and the bridge.

I have one problem but I’m not sure where to start troubleshoot…
I use this custumization along with Nuki integration and I want to use sensors and lock for automation with fingerprint module. I get sensor update (f.i. sensor.nuki_lock_sensor_state and
sensor.nuki_door_sensor_state ) with some delay. That is causing me some problems with locking doors with fingerprint sensor - for example: I step outside close the state of door nuki door sensor is still locked. It’s really anoyoning to wait for 15-30 sec to get sensor state refreshed.

First question: Since I use this costumization - is it safe to delete nuki integration?
Second question: Is delay caused by data routing to cloud or …?
Third question: Does anyone have instant status update in HA when state changes (door - > opened or closed; lock-> locked or unlocked)?

Thanks you in advance!

1 Like

1- The title of this thread is the answer (and I can confirm it from my own experience).
2- AFAIK Nuki cloud is not implicated in the process.
3- On my side, I have to wait a few seconds after the lock/unlock is physically finished to have the state change (but much less than 15-30 sec).

1 Like

I’m still seeing long delays with state update changes, for locking/unlocking and door open/close.

I’m going to roll back my instance to before installing the package version or the previous manual one and then reinstall the latest packages version again, to see if that helps.

Thanks you both.
@mahikeulbody I just recorded the time gap between changed state and state in HA…it is 2 min for lock → unlock and 1min20 sec for state from unlock-> lock.

@Sym0nd0 could you report if any change after reinstalling?

1 Like

Will do, I’m away until the weekend, so it won’t be for a few days.

1 Like

Waou, it is too much ! There is obviously a problem. Could you try removing the official integration ?

I did. The recorded time is after uninstalled integration. No change.

Here is my nuki_card_callback.yaml:

########################
# Nuki Card v6.0       #
########################

#######################################################################################################################
###                                                                                                                 ###
### Automations                                                                                                     ###
###                                                                                                                 ###
#######################################################################################################################

automation:
  - id: "nuki_card_callback"
    alias: Nuki Card Callback
    description: Automation for the Nuki doorlock
    trigger:
      - platform: webhook
        webhook_id: !secret nuki_bridge_webhook
      - platform: event
        event_type:
          - automation_reloaded
          - event_template_reloaded
      - platform: state
        entity_id: sensor.nuki_door_sensor_state
        to:
          - "open"
          - "closed"
      - platform: state
        entity_id: sensor.nuki_lock_sensor_state
        to:
          - "locked"
          - "unlocked"
    condition: []
    action:
      - choose:
          - conditions: >
              {{ trigger.platform == 'webhook' }}
            sequence:
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_door_sensor
                data:
                  value: >
                    {% set my_state = {1: 'deactivated', 2: 'closed', 3: 'open', 4: 'unknown', 5: 'calibrating'} %}
                    {{ my_state[trigger.json.doorsensorState] }}
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_lock_sensor
                data:
                  value: >
                    {% 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[trigger.json.state] }}
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_last_activity
                data:
                  value: >
                    {{ as_timestamp(now()) | timestamp_custom("%H:%M:%S (%b %d)") }}
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_trigger_platform
                data:
                  value: >
                    {{ trigger.platform }}
          - conditions: >
              {{ trigger.platform == 'state' or trigger.platform == 'event' }}
            sequence:
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_door_sensor
                data:
                  value: >
                    {{ states('sensor.nuki_door_sensor_state') }}
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_lock_sensor
                data:
                  value: >
                    {{ states('sensor.nuki_lock_sensor_state') }}
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_last_activity
                data:
                  value: >
                    {{ states('sensor.nuki_last_activity') }}
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_trigger_platform
                data:
                  value: >
                    {{ trigger.platform }}
        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: >
          {{ is_state('input_text.nuki_bridge_door_sensor', 'open') }}
        availability_template: >
          {{ (is_state('sensor.nuki_door_sensor_state', 'open') or is_state('sensor.nuki_door_sensor_state', 'closed')) }}
        icon_template: >
          {% set trigdoor = states('input_text.nuki_bridge_door_sensor') %}
          {% set triglock = states('input_text.nuki_bridge_lock_sensor') %}
          {% 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:
          trigger_platform: >
            {{ states('input_text.nuki_bridge_trigger_platform') }}
          nuki_id: >
            {{ states('sensor.nuki_id') }}
          door_state: >
            {{ states('input_text.nuki_bridge_door_sensor') }}
          lock_state: >
            {{ states('input_text.nuki_bridge_lock_sensor') }}
          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: >
            {{ states('input_text.nuki_bridge_last_activity') }}
          last_update_polled: >
            {{ states('sensor.nuki_last_activity') }}
          door_sensor_polled: >
            {{ states('sensor.nuki_door_sensor_state') }}
          lock_sensor_polled: >
            {{ states('sensor.nuki_lock_sensor_state') }}

#######################################################################################################################
###                                                                                                                 ###
### Input Texts                                                                                                     ###
###                                                                                                                 ###
#######################################################################################################################
input_text:
  nuki_bridge_host:
    name: "Nuki Card (bridge host)"
    initial: !secret nuki_bridge_host
  nuki_bridge_port:
    name: "Nuki Card (bridge port)"
    initial: !secret nuki_bridge_port
  nuki_bridge_token:
    name: "Nuki Card (bridge token)"
    initial: !secret nuki_bridge_token
  nuki_bridge_door_sensor:
    name: "Nuki Card (door sensor)"
  nuki_bridge_lock_sensor:
    name: "Nuki Card (lock sensor)"
  nuki_bridge_last_activity:
    name: "Nuki Card (last activity)"
  nuki_bridge_trigger_platform:
    name: "Nuki Card (trigger platform)"

#######################################################################################################################
###                                                                                                                 ###
### 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: >
      {{ is_state_attr('binary_sensor.nuki_door_state', 'lock_state', 'locked') or
        is_state_attr('binary_sensor.nuki_door_state', 'lock_state', 'unlocked')}}
    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('input_text.nuki_bridge_host') }}:{{ states('input_text.nuki_bridge_port') }}/lockAction?nukiId={{ states('sensor.nuki_id') }}&token={{ states('input_text.nuki_bridge_token') | urlencode }}&action={{ action }}"

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

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

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

  - 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 %}

      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 %}

      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 %}

      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 %}

      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 %}

      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 %}

      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 %}

      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 %}

      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 %}

      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 %}

      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 %}

      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:%S (%b %d)") }}
          {% endif %}

      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 %}

      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 %}

      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']] }}
          {% endif %}

      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
        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 %}

I think I figured it out. The sensor scan interval was set to 150, which corresponds the above mentioned time gap. I changed it to 10s when I tried, I immediately got state update when unlocking/locking to unlocking/locking and just after lock finished job the state updated!!!
@Sym0nd0 maybe try changing scan interval in nuki_card_callback.yaml :slight_smile:

The sensor scan interval is used for the polling of non important attributes of the lock : firmware version, last activity, etc… The state of both lock and door is retrieved through callback so it is done immediately or a few seconds after the event. Shortening scan interval is only a workaround which hides the real problem.

I think you have an error with the configuration of the callbacks.

This implementation works like a charm.
I hope the official Nuki integration will implement parts of this logic too in the near future.

OK, I didn’t know that, I thought scan interval was for both sensors (lock and door status).
Any suggestions where to look for errors…
I checked:

  • the fingerprint scaner and I got immediate response,
  • the Nuki app (via bluetooth) is much quicker that 2 mins (around 5-10 sec),
  • nuki_card_callback.yaml was c/p from this thread and I rechecked it, but I’m no programmer :slight_smile:
    …?
    Thanks!

There are some steps and requirements others than to copy&paste nuki_card_callback.yaml. You could check them also with the very complete description made by alexdelpetre in the first post of this thread.

1 Like