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

@alexdelprete, I came across an error in my automation and just corrected it.

Regarding the webhook, when I used the “!secret nuki_bridge_token” it didn’t work, so I had to put in the complete webhook. I don’t know if this is something from the UI or not. I will test it this evening.

Regarding the old syntax, this is how I got it to work, feel free to convert it to the new syntax.

Regarding blueprints, I have no experience with blueprinting except that I know it exists.

Regards,

Jeroen

But if you first prepare a sensor, that gets data from the !secret, you can then use states(sensor.name), like we already do for the token, the host, the port, in the rest sensor. I didn’t do it for the webhook because !secret was supported as the webhook_id. But we could bypass using the same workaround I used for the REST sensor. Check the following parts:

  - sensor:
    - name: "Nuki Bridge Host"
      state: !secret nuki_bridge_host

    - name: "Nuki Bridge Port"
      state: !secret nuki_bridge_port

    - name: "Nuki Bridge Token"
      state: !secret nuki_bridge_token
  - 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

template:
  - trigger:
      - platform: webhook
        webhook_id: !secret nuki_bridge_webhook
      - platform: event
        event_type: event_template_reloaded
      - platform: state
        entity_id: sensor.nuki_door_sensor_state
        to:
          - "open"
          - "closed"

With the new syntax, the trigger sensor generates a specific error when you put it into the package. So it’s not doable.

Let’s approach it in steps: first a package with this legacy syntax, that still works, then when we can convert it into the new syntax we’ll do it.

After the release of the first package, I’ll study blueprints and see if we can make a blueprint out of the package.

Thanks again, I’l start working on this as soon as possible so users can easily install it without issues.

Working on the package now…if everything works ok, I’ll release it this evening.

@spokin: I just installed the package, unfortunately the door sensor logic is wrong, if the lock is unlocked, the door sensor is always open. furthermore, all the trigger webhook logic is missing: the door sensor is linked only to the polling sensors, not to the webhook trigger. I need to rework the logic, I hope I can do the same things in the automation I did in the code for the template trigger. Let’s see…

the code here is not working:

    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

I understand a little bit more what you did: you didn’t simply repackage the code, you changed the logic of the main sensor, the trigger one, that takes the updates both from the polling rest sensors and from the callback.

Changing the logic unfortunately led to unintended consequences: that code is not doing what my integration did. you are refreshing the state rest sensors when called by the webhook. But that is not efficient, because when the bridge calls, it passes json data with the states of the lock and the door, so there’s no need to do the rest calls again.

I’ll try to reimplement the correct logic in this automation format, if it’s doable, ok, otherwise I will not publish the package in this format and with this inefficient logic. If I have to give up the efficiency and logic of the code for ease of configuration, I will leave the configuration as it is for now, until they let the template trigger sensor be packaged.

Will keep you updated…

@alexdelprete I implemented the action of updating the sensor.nuki_endpoint_list and sensor.nuki_endpoint_info in case for example HA is restarted and the state of the nuki changes when HA is offline. In that case the input_boolean will get the last state it had before HA went down. So after HA is back, it might show the wrong state. That is also why I trigger the automation at startup of HA. On the other hand, I understand the inefficiency, so probably I need to split up the automation, one for the start of HA with update_entity action and one for the other 3 triggers with in the latter one it will not fire when HA is starting up otherwise you’ll get 2 updates because of the possible triggering via sensor.nuki_door_sensor_state.

@alexdelprete adding sensor.nuki_bridge_token as the value of the webhook_id seems to work. So there will be no need to add in the webhook _id manually.

Can anyone help with that:
curl -X GET -H “Content-Type: application/json” ‘http://192.168.88.180:8080/callback/add?token=XXXXX
HTTP 400 bad request

I’ve checked with a list and only one ID is registered, also the previous command registering webhook finished with success…

Works now with @spokin package - don’t know why it didn’t work when I copy&pasted everything from 1st post… all I did now to make this work is to paste webhook from secrets.yaml and that’s it, removed everything except secrets.yaml contents. I restarted HA after completing 1st post instruction - should I reboot the whole server or something?

All these things you are concerned about have already been analyzed with the other friends in this thread for a couple of months (in particular with @Friedrieck) and I personally ran all kind of tests: when HA starts up the state trigger and the reload event triggers are more than enough to bring all sensors to the proper state. REST sensors are called at startup and they populate all the needed info, so there’s no need to redo a REST call every time the automation is triggered.

Another important thing that’s missing in your code: when the webhook is triggered, you also receive a json payload from the bridge, with the updated states of the devices installed: door sensor, lock, etc. so there’s no need to call the rest sensors to retrieve the info again, that is the main inefficiency. If you open the door, the bridge callsback and tells you that the door is open, what you do with your code is query the bridge AGAIN to retrieve all info, even if the bridge already passed you the info. Basically, you are using the callback as a signal to start the polling. That’s the main inefficiency.

The logic we used basically was a triggered sensor that got the updates BOTH from the callback’s json payload, AND from the REST sensors when they polled the bridge. So you have the best of all 2 techniques: polling + callbacks.

Anyway, I had to study how the automation platform worked and how the conditionals worked to reimplement the same logic used with the “modern syntax”, so basically I ported the code (and logic) from new to legacy style so we can publish a package. In order to do it, I had to use input_texts as global variables for the automation, since the binary_sensor is not part of the automation.

I also tried the webhook_id pulling data from secrets: it works. I don’t know why it didn’t work for you.

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: event_template_reloaded
      - platform: state
        entity_id: sensor.nuki_door_sensor_state
        to:
          - "open"
          - "closed"

I also imported the other 3 secret info needed (host, port, token) into input_texts:

input_text:
  nuki_bridge_host:
    initial: !secret nuki_bridge_host
  nuki_bridge_port:
    initial: !secret nuki_bridge_port
  nuki_bridge_token:
    initial: !secret nuki_bridge_token
  nuki_bridge_door_sensor:
  nuki_bridge_lock_sensor:
  nuki_bridge_last_activity:
  nuki_bridge_trigger_platform:

So the user has to configure only the 4 secrets (host, port, token, webhook), put the file in the packages subdir, and reference it in config.yaml. Much simpler to configure, while keeping the same efficient logic as the other code.

A request to all users of the Nuki Card: here’s the refactored version in package format. I basically had to port everything to the automation platform with the legacy syntax (that I don’t like at all). The new Template trigger syntax is far more efficient and logical, but unfortunately can’t be packaged, so based on the input of @spokin, I completed a working packaged version. It works here, I tested it for 2hrs, but before officially releasing it, I need your help. At least 4-5 people should kindly test it and report if it’s working.

You need the same 4 secrets items in secrets.yaml (host, port, token and webhook), plus you need to create a folder called packages in the main CONFIG folder, and in that folder you create a file called nuki_card_callback.yaml, and you paste this code at the bottom of the post in it.

nuki_bridge_host: "nuki-bridge.axel.dom"
nuki_bridge_port: "8080"
nuki_bridge_token: "txxxxhl"
nuki_bridge_webhook: eyJ0eXAiOiJKVxyxyxyxyxyxyxyxy1NiJ9.eyJpc3MiOiI3OGQxMDJk

Then, in configuration.yaml, under the homeassistant: section you reference the directory containing all packages:

image

Here’s the code for nuki_card_callback.yaml:

########################
# Nuki Card v6.0-rc2   #
########################

#######################################################################################################################
###                                                                                                                 ###
### 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: 150
    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: 150
    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 %}
2 Likes

@alexdelprete You came to the same solution as I did, going to make use of the input_text. I was half the way of implementing it and was starting to finish it when I read your post. Thnx.

I’ll try it later today, but not as package but as fully split configuration (every sensor in separate file) - that’s how my current configuration has been set now to work, and package is used to load everything.

Is there an open ticket for this issue ?

@alexdelprete intalled your package - everything works fine, the one problem I had is solved with door sensor reporting open state all time so let’s wait for further testing and see if anyone reports issues, I’ll test this over weekend I reply todays evening in between Euro games
Cheers for your work!

@mahikeulbody Yes there is an open ticket see https://community.home-assistant.io/t/allow-integration-template-in-packages/305865. Unfortunately Frenck closed it for this reason: https://github.com/home-assistant/core/issues/49212#issuecomment-834520809.

@cpu I see it too.

@alexdelprete I see that a lot of sensors retrieve their values from the sensor.nuki_endpoint_list and sensor.nuki_endpoint_info. Isn’t it better to retrieve them from the binary sensor where possible? As far as I have experienced it now the sensor.nuki_endpoint_list and sensor.nuki_endpoint_info are only updated while you lock or unlock the door from lock.nuki_lock_action within HA. However if you you lock or unlock the door from lock.nuki_lock_action within HA or any other way, a webhook will be sent to HA so the automation nuki_card_callback is triggered and the binary sensor is updated. This update of the binary sensor will then trigger the update of all depending sensors. What do you think?

Ok. So, is this approach :

Let’s approach it in steps: first a package with this legacy syntax, that still works, then when we can convert it into the new syntax we’ll do it.

a good one if we are not sure this issue will be solved someday when, at the same time, we are almost sure that the legacy syntax will be removed soon or late ?

I don’t know if the legacy syntax will be removed ever. When they will do that, I think a lot of users will end up with a non working HA system when they upgrade. I think this would kill HA. But this is my personal opinion, Maybe all references to the old syntax will be removed from the documentation so you can’t find any references to it any more in the official documentation.

The solution is simply the same thing I did with the split code, same logic. Check the use of the platform to update the input_texts, that’s the core difference in regards to the efficiency I mentioned in my previous comment regarding how you made it. If you look at the code, what I do is: if the trigger is the webhook, I use data from the callback that is immediately available, if the trigger is state/event, I take data from the polled sensors. Without doing unneeded REST calls. So you have the triggered data and the polled data, both refreshing the sensors.

Now we need to test it thouroughly before releasing it.