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

Hi Alessandro,
installed V8.3 and I had the same entries (like @jezinke got) in the log after ~ 1 hour.
Now, after I updated HA from V 2021.7.0 to V 2021.7.4 there is nothing anymore for 2 hours.
But this can’t be because of the update, or?

Alas, I’m now seeing errors too (I’ve not updated to v2021.7.4 yet).

2021-07-24 10:34:21 WARNING (MainThread) [homeassistant.helpers.entity] Update of sensor.nuki_bridge_callback_list is taking over 10 seconds
2021-07-24 10:34:21 ERROR (MainThread) [homeassistant.components.rest.data] Error fetching data: http://192.168.1.41:8080/callback/list?&token=<edit> failed with
2021-07-24 10:34:21 WARNING (MainThread) [homeassistant.components.rest.sensor] Empty reply found when expecting JSON data
2021-07-24 10:34:21 WARNING (MainThread) [homeassistant.helpers.entity] Update of sensor.nuki_bridge_endpoint_list is taking over 10 seconds
2021-07-24 10:34:21 WARNING (MainThread) [homeassistant.helpers.entity] Update of sensor.nuki_bridge_endpoint_info is taking over 10 seconds
2021-07-24 10:34:21 ERROR (MainThread) [homeassistant.components.automation.nuki_card_callback] Nuki Card Callback: Choose at step 1: choice 2: Error executing script. Error for call_service at pos 1: Error rendering data template: JSONDecodeError: Expecting value: line 1 column 1 (char 0)
2021-07-24 10:34:21 ERROR (MainThread) [homeassistant.components.rest.data] Error fetching data: http://192.168.1.41:8080/list?&token=<edit> failed with
2021-07-24 10:34:21 WARNING (MainThread) [homeassistant.components.rest.sensor] Empty reply found when expecting JSON data
2021-07-24 10:34:21 ERROR (MainThread) [homeassistant.components.automation.nuki_card_callback] Nuki Card Callback: Error executing script. Error for choose at pos 1: Error rendering data template: JSONDecodeError: Expecting value: line 1 column 1 (char 0)
2021-07-24 10:34:21 ERROR (MainThread) [homeassistant.components.automation.nuki_card_callback] Error while executing automation automation.nuki_card_callback: Error rendering data template: JSONDecodeError: Expecting value: line 1 column 1 (char 0)
2021-07-24 10:34:21 ERROR (MainThread) [homeassistant.components.rest.data] Error fetching data: http://192.168.1.41:8080/info?&token=<edit> failed with
2021-07-24 10:34:21 WARNING (MainThread) [homeassistant.components.rest.sensor] Empty reply found when expecting JSON data

It all appears to be functioning as expected though. :confused:

Five hours later:


Can it be the bridge goes into a sleeping / power saving mode?

@Joerg, @Sym0nd0, @jezinke : for sure there are some problems, after some time the automation’s running, that cause communication failures with the bridge. In v8.2 I tried to minimize the parallel execution of REST calls to the bridge to the minimum, and reports from you guys looked good, in v8.3 I simply optimized some code (not regarding the rest communication) and tweaked the configuration of the automation. So what I ask you to try is to change line 16 of the code, from max: 5 to max: 3 and restart HA.

Let’s see if it improves things regarding comms with the bridge.

Thanks for your help guys.

1 Like

Hi,
nope, I got the same warnings in my log.

Amended as requested and rebooted, my logs currently only show

2021-07-24 17:34:27 WARNING (MainThread) [homeassistant.components.sensor] Platform rest not ready yet: Unsupported URL protocol ''; Retrying in background in 30 seconds
2021-07-24 17:34:27 WARNING (MainThread) [homeassistant.components.sensor] Platform rest not ready yet: Unsupported URL protocol ''; Retrying in background in 30 seconds
2021-07-24 17:34:27 WARNING (MainThread) [homeassistant.components.sensor] Platform rest not ready yet: Unsupported URL protocol ''; Retrying in background in 30 seconds

I’ll leave it an hour or so, check again and update you.

Show me the log please.

Those warnings are ok, at boot the rest sensors variables are not initialized yet, so it gives you the warning. Warnings don’t bother mee too much, we’re looking for errors, specifically: communication errors.

Let me know…

got the same warning and error. I tried to match the HA log entries with the Nuki log and found the folloing situation:
HA log
2021-07-24 18:09:08 WARNING (MainThread) [homeassistant.helpers.entity] Update of sensor.nuki_bridge_endpoint_info is taking over 10 seconds

2021-07-24 18:09:08 WARNING (MainThread) [homeassistant.helpers.entity] Update of sensor.nuki_bridge_callback_list is taking over 10 seconds

2021-07-24 18:09:08 ERROR (MainThread) [homeassistant.components.rest.data] Error fetching data: http://192.168.1.47:8080/info?&token=ucqbkj failed with

2021-07-24 18:09:08 WARNING (MainThread) [homeassistant.components.rest.sensor] Empty reply found when expecting JSON data

2021-07-24 18:09:09 ERROR (MainThread) [homeassistant.components.rest.data] Error fetching data: http://192.168.1.47:8080/callback/list?&token=ucqbkj failed with

2021-07-24 18:09:09 WARNING (MainThread) [homeassistant.components.rest.sensor] Empty reply found when expecting JSON data

2021-07-24 18:09:09 ERROR (MainThread) [homeassistant.components.automation.nuki_card_callback] Nuki Card Callback: Choose at step 1: choice 2: Error executing script. Error for call_service at pos 1: Error rendering data template: JSONDecodeError: Expecting value: line 1 column 1 (char 0)

2021-07-24 18:09:09 ERROR (MainThread) [homeassistant.components.automation.nuki_card_callback] Nuki Card Callback: Error executing script. Error for choose at pos 1: Error rendering data template: JSONDecodeError: Expecting value: line 1 column 1 (char 0)

2021-07-24 18:09:09 ERROR (MainThread) [homeassistant.components.automation.nuki_card_callback] Error while executing automation automation.nuki_card_callback: Error rendering data template: JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Nuki log
{“timestamp”: “2021-07-24T16:09:18+00:00”, “nukiId”: “192ABBDD”, “type”: “BLE-Connect”, “pairIndex”: 0},
{“timestamp”: “2021-07-24T16:09:18+00:00”, “type”: “SSE-TimeResponse”},
{“timestamp”: “2021-07-24T16:09:08+00:00”, “type”: “SSE-PushNukisResponse”},
{“timestamp”: “2021-07-24T16:09:08+00:00”, “type”: “SSE-PushNukisRequest”, “count”: 1},
{“timestamp”: “2021-07-24T16:09:08+00:00”, “type”: “SSE-Gettime”},
{“timestamp”: “2021-07-24T16:09:08+00:00”, “type”: “SSE-Connected”, “serverNum”: 8},
{“timestamp”: “2021-07-24T16:09:08+00:00”, “type”: “SSE-PushNukisRequest”, “count”: 1},
{“timestamp”: “2021-07-24T16:09:04+00:00”, “type”: “WLAN-Connected”, “ipAddr”: “192.168.1.47”},

Seems like the Nuki Bridge is busy and not responding or refusing HTTP Requests.

2021-07-24 18:42:30 ERROR (MainThread) [homeassistant.components.rest.data] Error fetching data: http://192.168.0.*:8081/callback/list?&token=* failed with illegal status line: bytearray(b'5C')
2021-07-24 18:42:30 WARNING (MainThread) [homeassistant.components.rest.sensor] Empty reply found when expecting JSON data
2021-07-24 18:42:30 ERROR (MainThread) [homeassistant.components.automation.nuki_card_callback] Nuki Card Callback: Choose at step 1: choice 2: Error executing script. Error for call_service at pos 1: Error rendering data template: JSONDecodeError: Expecting value: line 1 column 1 (char 0)
2021-07-24 18:42:30 ERROR (MainThread) [homeassistant.components.automation.nuki_card_callback] Nuki Card Callback: Error executing script. Error for choose at pos 1: Error rendering data template: JSONDecodeError: Expecting value: line 1 column 1 (char 0)
2021-07-24 18:42:30 ERROR (MainThread) [homeassistant.components.automation.nuki_card_callback] Error while executing automation automation.nuki_card_callback: Error rendering data template: JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Yes, you are right. But I don’t understand why that happens, I mean, if it’s something the code does that brings the bridge in that state or something we can’t control.

Thinking…

Thanks.

The first line is the problem:

2021-07-24 18:42:30 ERROR (MainThread) [homeassistant.components.rest.data] Error fetching data: http://192.168.0.:8081/callback/list?&token= failed with illegal status line: bytearray(b’5C’)

The other lines are the product of that one.

{"timestamp": "2021-07-24T16:44:28+00:00", "type": "HTTP-Info"},
{"timestamp": "2021-07-24T16:42:28+00:00", "type": "HTTP-List"},
{"timestamp": "2021-07-24T16:42:28+00:00", "type": "HTTP-Info"},
{"timestamp": "2021-07-24T16:40:28+00:00", "type": "HTTP-Info"},
{"timestamp": "2021-07-24T16:40:28+00:00", "type": "HTTP-List"},

The Bridge log (times are UTC = - 2 hours)

So the bridge was answering, it was not rebooting or busy…mmm… you only have those HTTP-Info/List entries?

Yes, and there is a 2 second time difference. Bridge says 18:42:28 and the error in HA log was at 18:42:30

1-2 secs is probably the round-trip time from the request to the answer plus the logging.

I changed the scan_interval (the polling period) of the 3 rest sensors to avoid having them call the bridge in the same second. 1st polls every 90 secs, 2nd every 120 secs, 3rd every 130 secs.

Please try this v8.4-rc1 version and let me know (correlate HA logs with bridge log like you did before). Thanks.

########################
# Nuki Card v8.4-rc1   #
########################

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

automation:
  - id: "nuki_card_callback"
    alias: Nuki Card Callback
    description: Automation for the Nuki doorlock
    mode: queued
    max: 5
    max_exceeded: warning
    trigger:
      - platform: homeassistant
        id: 'trigger_nuki_ha_start'
        event: start
      - platform: webhook
        id: 'trigger_nuki_bridge_webhook'
        webhook_id: !secret nuki_bridge_webhook
      - platform: state
        id: 'trigger_nuki_door_sensor_polled'
        entity_id: sensor.nuki_door_sensor_state
      - platform: state
        id: 'trigger_nuki_lock_sensor_polled'
        entity_id: sensor.nuki_lock_sensor_state
      - platform: state
        id: 'trigger_nuki_bridge_callback_list'
        entity_id: sensor.nuki_bridge_callback_list
    condition: []
    action:
      - choose:
          - conditions: >
              {{ trigger.id == 'trigger_nuki_bridge_webhook' }}
            sequence:
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_callback_url
                data:
                  value: >
                    {{ states('input_text.nuki_ha_internal_url') | urlencode }}/api/webhook/{{ states('input_text.nuki_bridge_webhook') | urlencode }}
          - conditions: >
              {{ trigger.id == 'trigger_nuki_bridge_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_id
                data:
                  value: >
                    {{ trigger.id }}
              - service: homeassistant.update_entity
                target:
                  entity_id: binary_sensor.nuki_door_state
              - service: homeassistant.update_entity
                target:
                  entity_id: lock.nuki_lock_action
          - conditions: >
              {{ trigger.id == 'trigger_nuki_bridge_callback_list' }}
            sequence:
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_callback_list
                data:
                  value: >
                    {{ (states('sensor.nuki_bridge_callback_list')|from_json) if states('sensor.nuki_bridge_callback_list') != 'unknown' }}
              - service: homeassistant.update_entity
                target:
                  entity_id: binary_sensor.nuki_bridge_callback
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_trigger_id
                data:
                  value: >
                    {{ trigger.id }}
              - service: script.nuki_bridge_check_callback
          - conditions: >
              {{ trigger.id in ['trigger_nuki_door_sensor_polled', 'trigger_nuki_lock_sensor_polled'] }}
            sequence:
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_door_sensor
                data:
                  value: >
                    {{ states('sensor.nuki_door_sensor_state') if states('sensor.nuki_door_sensor_state') != 'unknown' }}
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_lock_sensor
                data:
                  value: >
                    {{ states('sensor.nuki_lock_sensor_state') if states('sensor.nuki_lock_sensor_state') != 'unknown' }}
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_last_activity
                data:
                  value: >
                    {{ states('sensor.nuki_last_activity') if states('sensor.nuki_last_activity') != 'unknown' }}
              - service: input_text.set_value
                target:
                  entity_id: input_text.nuki_bridge_trigger_id
                data:
                  value: >
                    {{ trigger.id }}
        default: []


#######################################################################################################################
###                                                                                                                 ###
### Input Texts & Numbers                                                                                           ###
###                                                                                                                 ###
#######################################################################################################################
input_text:
  nuki_bridge_url:
    name: "Nuki Card (bridge url)"
    initial: !secret nuki_bridge_url
  nuki_bridge_token:
    name: "Nuki Card (bridge token)"
    initial: !secret nuki_bridge_token
  nuki_bridge_webhook:
    name: "Nuki Card (bridge webhook)"
    initial: !secret nuki_bridge_webhook
    max: 500
  nuki_ha_internal_url:
    name: "Nuki Card (HA internal URL)"
    initial: !secret nuki_ha_internal_url
  nuki_bridge_callback_list:
    name: "Nuki Card (bridge callback list)"
  nuki_bridge_callback_url:
    name: "Nuki Card (bridge callback url)"
    max: 500
  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_id:
    name: "Nuki Card (trigger id)"


#######################################################################################################################
###                                                                                                                 ###
### 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: >
          {{ states('input_text.nuki_bridge_door_sensor') != 'unknown' or states('sensor.nuki_door_sensor_state') != 'unknown' }}
        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_id: >
            {{ states('input_text.nuki_bridge_trigger_id') if states('input_text.nuki_bridge_trigger_id') != 'unknown' }}
          bridge_callback_id_list: >
            {{ states('input_text.nuki_bridge_callback_list')|from_json if is_state('binary_sensor.nuki_bridge_callback', 'on') else "not configured" }}
          nuki_id: >
            {{ states('sensor.nuki_id') if states('sensor.nuki_id') != 'unknown' }}
          door_state: >
            {{ states('input_text.nuki_bridge_door_sensor') if states('input_text.nuki_bridge_door_sensor') != 'unknown' }}
          lock_state: >
            {{ states('input_text.nuki_bridge_lock_sensor') if states('input_text.nuki_bridge_lock_sensor') != 'unknown' }}
          lock_battery: >
            {{ states('sensor.nuki_lock_battery_level') if states('sensor.nuki_lock_battery_level') != 'unknown' }}
          lock_battery_critical: >
            {{ states('sensor.nuki_lock_battery_critical_state') if states('sensor.nuki_lock_battery_critical_state') != 'unknown' }}
          keypad_battery_critical: >
            {{ states('sensor.nuki_keypad_battery_critical_state') if states('sensor.nuki_keypad_battery_critical_state') != 'unknown' else "not installed" }}
          last_activity_callback: >
            {{ states('input_text.nuki_bridge_last_activity') if states('input_text.nuki_bridge_last_activity') != 'unknown' }}
          last_activity_polled: >
            {{ states('sensor.nuki_last_activity') if states('sensor.nuki_last_activity') != 'unknown' }}
          door_sensor_polled: >
            {{ states('sensor.nuki_door_sensor_state') if states('sensor.nuki_door_sensor_state') != 'unknown' }}
          lock_sensor_polled: >
            {{ states('sensor.nuki_lock_sensor_state') if states('sensor.nuki_lock_sensor_state') != 'unknown' }}

      nuki_bridge_callback:
        unique_id: nuki_bridge_callback
        friendly_name: "Nuki Bridge Callback"
        icon_template: mdi:arrow-vertical-lock
        value_template: >
          {% if states('sensor.nuki_bridge_callback_list') != 'unknown' and states('input_text.nuki_bridge_callback_list')|count > 0 %}
            {{ 'on' if states('input_text.nuki_bridge_callback_list')|from_json|count == 1 else 'off' }}
          {% else %}
            off
          {% endif %}
        attribute_templates:
          callback_id_list: >
            {{ states('sensor.nuki_bridge_callback_list') if states('sensor.nuki_bridge_callback_list') != 'unknown' }}


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

lock:
  - platform: template
    name: "Nuki Lock Action"
    unique_id: nuki_lock_action
    value_template: >
      {{ is_state('input_text.nuki_bridge_lock_sensor','locked') if is_state('input_text.nuki_bridge_lock_sensor','locked') != 'unknown' }}
    availability_template: >
      {{ states('input_text.nuki_bridge_lock_sensor') != 'unknown' or states('sensor.nuki_lock_sensor_state') != 'unknown' }}
    lock:
      service: rest_command.nuki_lock_action
      data:
        action: 2
    unlock:
      service: rest_command.nuki_lock_action
      data:
        action: 1


#######################################################################################################################
###                                                                                                                 ###
### scripts                                                                                                         ###
###                                                                                                                 ###
#######################################################################################################################

script:
  nuki_bridge_check_callback:
    sequence:
      - alias: "Add callback to bridge"
        repeat:
          while: "{{ states('binary_sensor.nuki_bridge_callback') == 'off' and states('input_text.nuki_bridge_callback_list')|from_json|count == 0 }}"
          sequence:
            - service: rest_command.nuki_bridge_add_callback
            - delay: 5
            - service: homeassistant.update_entity
              target:
                entity_id: sensor.nuki_bridge_callback_list
            - service: homeassistant.update_entity
              target:
                entity_id: binary_sensor.nuki_bridge_callback
            - service: input_text.set_value
              target:
                entity_id: input_text.nuki_bridge_callback_list
              data:
                value: >
                  {{ states('sensor.nuki_bridge_callback_list')|from_json if states('sensor.nuki_bridge_callback_list') != 'unknown' }}
            - wait_template: "{{ is_state('binary_sensor.nuki_bridge_callback', 'on') and states('input_text.nuki_bridge_callback_list')|from_json|count == 1 }}"
              timeout: 10
            - service: persistent_notification.create
              data:
                notification_id: "nuki_card_persistent"
                title: Nuki Card (added callback to bridge)
                message: >
                  * [**Script nuki_bridge_check_callback**] ran at {{ as_timestamp(now()) | timestamp_custom("%H:%M:%S (%b %d)") }}

                  * [**Bridge Callback ID:**] "{{ states('input_text.nuki_bridge_callback_list') }}"
                  
                  * [**Callback Raw List:**] {{ state_attr('sensor.nuki_bridge_callback_list','callbacks') }}
      - alias: "Delete callbacks from bridge"
        repeat:
          while: "{{ (states('input_text.nuki_bridge_callback_list')|from_json|count > 1) }}"
          sequence:
            - service: rest_command.nuki_bridge_del_callback
              data:
                callback_id: "{{ (states('input_text.nuki_bridge_callback_list')|from_json)[-1] }}"
            - delay: 5
            - service: homeassistant.update_entity
              target:
                entity_id: sensor.nuki_bridge_callback_list
            - service: homeassistant.update_entity
              target:
                entity_id: binary_sensor.nuki_bridge_callback
            - service: input_text.set_value
              target:
                entity_id: input_text.nuki_bridge_callback_list
              data:
                value: >
                  {{ states('sensor.nuki_bridge_callback_list')|from_json if states('sensor.nuki_bridge_callback_list') != 'unknown' }}
            - service: persistent_notification.create
              data:
                notification_id: "nuki_card_persistent"
                title: Nuki Card (deleted callback to bridge)
                message: >
                  * [**Script nuki_bridge_check_callback**] ran at {{ as_timestamp(now()) | timestamp_custom("%H:%M:%S (%b %d)") }}

                  * [**Bridge Callback ID:**] "{{ states('input_text.nuki_bridge_callback_list') }}"
                  
                  * [**Callback Raw List:**] {{ state_attr('sensor.nuki_bridge_callback_list','callbacks') }}


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

rest_command:
  nuki_lock_action:
    url: "{{ states('input_text.nuki_bridge_url') }}/lockAction?nukiId={{ states('sensor.nuki_id') }}&action={{ action }}&token={{ states('input_text.nuki_bridge_token') | urlencode }}"
  nuki_bridge_add_callback:
    url: "{{ states('input_text.nuki_bridge_url') }}/callback/add?url={{ states('input_text.nuki_bridge_callback_url') }}&token={{ states('input_text.nuki_bridge_token') | urlencode }}"
  nuki_bridge_del_callback:
    url: "{{ states('input_text.nuki_bridge_url') }}/callback/remove?id={{ callback_id|int }}&token={{ states('input_text.nuki_bridge_token') | urlencode }}"


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

sensor:
  - platform: rest
    scan_interval: 90
    resource_template: >
      {% if states('input_text.nuki_bridge_url') != 'unknown' and states('input_text.nuki_bridge_token') != 'unknown' %}
        {{ states('input_text.nuki_bridge_url') }}/callback/list?&token={{ states('input_text.nuki_bridge_token') | urlencode }}
      {% endif %}
    name: "Nuki Bridge Callback List"
    force_update: true
    value_template: >
      {% set ns = namespace() %}
      {% set ns.callback_list = [] %}
      {% if (value_json.callbacks | count) > 0 %}
        {% set hook = states('input_text.nuki_bridge_callback_url') %}
        {% for callback in value_json.callbacks %}
          {% if hook == (callback.url|urlencode) %}
            {% set ns.callback_list = ns.callback_list + [ callback.id ] %}
          {% endif %}
        {% endfor %}
      {% endif %}
      {{ ns.callback_list }}
    json_attributes:
      - callbacks

  - platform: rest
    scan_interval: 120
    resource_template: >
      {% if states('input_text.nuki_bridge_url') != 'unknown' and states('input_text.nuki_bridge_token') != 'unknown' %}
        {{ states('input_text.nuki_bridge_url') }}/list?&token={{ states('input_text.nuki_bridge_token') | urlencode }}
      {% endif %}
    name: "Nuki Bridge Endpoint List"
    force_update: false
    value_template: "OK"
    json_attributes:
      - lastKnownState
      - firmwareVersion
      - nukiId
      - name

  - platform: rest
    scan_interval: 130
    resource_template: >
      {% if states('input_text.nuki_bridge_url') != 'unknown' and states('input_text.nuki_bridge_token') != 'unknown' %}
        {{ states('input_text.nuki_bridge_url') }}/info?&token={{ states('input_text.nuki_bridge_token') | urlencode }}
      {% endif %}
    name: "Nuki Bridge Endpoint Info"
    force_update: false
    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: >
          {{ state_attr('sensor.nuki_bridge_endpoint_info','scanResults')[0]['name'] if states('sensor.nuki_bridge_endpoint_info') == "OK" }}

      nuki_bridge_fw_version:
        unique_id: nuki_bridge_fw_version
        friendly_name: "Nuki Bridge FW Version"
        icon_template: mdi:numeric
        value_template: >
          {{ state_attr('sensor.nuki_bridge_endpoint_info','versions')['firmwareVersion'] if states('sensor.nuki_bridge_endpoint_info') == "OK" }}

      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: >
          {{ state_attr('sensor.nuki_bridge_endpoint_info','scanResults')[0]['rssi'] if states('sensor.nuki_bridge_endpoint_info') == "OK" }}

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

      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: >
          {{ state_attr('sensor.nuki_bridge_endpoint_info','versions')['wifiFirmwareVersion'] if states('sensor.nuki_bridge_endpoint_info') == "OK" }}

      nuki_bridge_cloud_connected:
        unique_id: nuki_bridge_cloud_connected
        friendly_name: "Nuki Bridge Cloud Connected"
        icon_template: mdi:server-network
        value_template: >
          {{ state_attr('sensor.nuki_bridge_endpoint_info','serverConnected') if states('sensor.nuki_bridge_endpoint_info') == "OK" }}

      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_bridge_endpoint_info') == "OK" %}
            {% if state_attr('sensor.nuki_bridge_endpoint_info','scanResults')[0]['paired'] %}
              mdi:bluetooth-connect
            {% elif not state_attr('sensor.nuki_bridge_endpoint_info','scanResults')[0]['paired'] %}
              mdi:bluetooth-off
            {% else %}
              mdi:bluetooth-audio
            {% endif %}
          {% endif %}
        value_template: >
          {% if states('sensor.nuki_bridge_endpoint_info') == "OK" %}
            {% if state_attr('sensor.nuki_bridge_endpoint_info','scanResults')[0]['paired'] %}
              connected
            {% elif not state_attr('sensor.nuki_bridge_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: >
          {{ state_attr('sensor.nuki_bridge_endpoint_list','nukiId') if states('sensor.nuki_bridge_endpoint_list') == "OK" }}

      nuki_lock_fw_version:
        unique_id: nuki_lock_fw_version
        friendly_name: "Nuki Lock FW Version"
        icon_template: mdi:numeric
        value_template: >
          {{ state_attr('sensor.nuki_bridge_endpoint_list','firmwareVersion') if states('sensor.nuki_bridge_endpoint_list') == "OK" }}

      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: >
          {{ state_attr('sensor.nuki_bridge_endpoint_list','lastKnownState')['batteryCritical'] if states('sensor.nuki_bridge_endpoint_list') == "OK" }}

      nuki_friendly_name:
        unique_id: nuki_friendly_name
        friendly_name: "Nuki Friendly Name"
        icon_template: mdi:alphabetical-variant
        value_template: >
          {{ state_attr('sensor.nuki_bridge_endpoint_list','name') if states('sensor.nuki_bridge_endpoint_list') == "OK" }}

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

      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_bridge_endpoint_list') == "OK" %}
            {% set battery_level = state_attr('sensor.nuki_bridge_endpoint_list', 'lastKnownState')['batteryChargeState'] | default(0) | int %}
            {% set battery_charging = state_attr('sensor.nuki_bridge_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_bridge_endpoint_list') == "OK" %}
            {% set battery_level = state_attr('sensor.nuki_bridge_endpoint_list', 'lastKnownState')['batteryChargeState'] | default(0) | int %}
            {% if state_attr('sensor.nuki_bridge_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_bridge_endpoint_list') == "OK" %}
            {% set door_icon = state_attr('sensor.nuki_bridge_endpoint_list', 'lastKnownState')['doorsensorState'] %}
            {% set lock_icon = state_attr('sensor.nuki_bridge_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_bridge_endpoint_list') == "OK" %}
            {% set my_state = {1: 'deactivated', 2: 'closed', 3: 'open', 4: 'unknown', 5: 'calibrating'} %}
            {{ my_state[state_attr('sensor.nuki_bridge_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_bridge_endpoint_list') == "OK" %}
            {% set lock_icon = state_attr('sensor.nuki_bridge_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_bridge_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_bridge_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_bridge_endpoint_list') == "OK" %}
            {% if state_attr('sensor.nuki_bridge_endpoint_list', 'lastKnownState')['keypadBatteryCritical'] != null %}
              {{ state_attr('sensor.nuki_bridge_endpoint_list', 'lastKnownState')['keypadBatteryCritical'] }}
            {% else %}
              not installed 
            {% endif %}
          {% endif %}

installed v8.4-rc1 about 45 minutes ago, so far no errors in HA log and no reboots in Nuki log. There are 3 no warning in HA log I never had bevor it might be from nuki card:
2021-07-24 19:33:17 WARNING (MainThread) [homeassistant.components.sensor] Platform rest not ready yet: Unsupported URL protocol ‘’; Retrying in background in 30 seconds

2021-07-24 19:33:17 WARNING (MainThread) [homeassistant.components.sensor] Platform rest not ready yet: Unsupported URL protocol ‘’; Retrying in background in 30 seconds

2021-07-24 19:33:17 WARNING (MainThread) [homeassistant.components.sensor] Platform rest not ready yet: Unsupported URL protocol ‘’; Retrying in background in 30 seconds

Just a question for my understanding: why is the bridge polled with list,log and callback so often? Shouldn’t the callback deliver all status changes in the lock automatically?

Installed v8.4-rc1 - after approx 30 minutes this showed up:

2021-07-24 20:20:34 WARNING (MainThread) [homeassistant.helpers.entity] Update of sensor.nuki_bridge_endpoint_list is taking over 10 seconds
2021-07-24 20:20:34 ERROR (MainThread) [homeassistant.components.rest.data] Error fetching data: http://192.168.0.*:8081/list?&token=* failed with 
2021-07-24 20:20:34 WARNING (MainThread) [homeassistant.components.rest.sensor] Empty reply found when expecting JSON data
2021-07-24 20:20:37 ERROR (MainThread) [homeassistant.components.rest.data] Error fetching data: http://192.168.0.*:8081/info?&token=* failed with [Errno 113] Connect call failed ('192.168.0.*', 8081)
2021-07-24 20:20:37 WARNING (MainThread) [homeassistant.components.rest.sensor] Empty reply found when expecting JSON data

Sorry, I am off for tonight. Cu tom.

Like I wrote in first post: REST sensors are used to gather ALL info from the system, some info from LIST command and the rest from the INFO command. And then I introduced a 3rd rest sensor for the configuration of the bridge callback feature.

120 secs is not often, 5 secs would be often, maybe. I can’t understand why the bridge becomes so unresponsive sometimes.