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

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.

Well, you can split it as you want now, the core has been ported so the package works, you can manipulate it as you prefer. :slight_smile:

Let me know if it works though, so we can release it. Keep in mind that I don’t like this approach very much, in order to make it work I had to use “global variables” (input_text). The original solution is much more “elegant”. :slight_smile:

I have no issues locally. What did you find wrong? What did you fix?

It’s not only a matter of style, but functionality and efficiency. The fact that with the new Template Trigger sensor the sensors you create are part of the platform, and not separate is more efficient because from the binary_sensor and the sensors created, you can access to the trigger data, without using tricks like globals/input_texts.

BTW: did you test the !secret for webhook? Does it now work for you?

This is what I was talking about in my previous comment. I understood where the devs are going with the template platform/integration. I like where they’re going, but obviously there are consequences…

This is exactly what I tried to explain you in my previous comments.

If you check Nuki Bridge API, you’ll notice that the json payload info it sends with the callback is minimal, only the status of the door sensor and the lock (and battery). Why? Because the callback has to be focused on IMPORTANT sensors, not all the info sensors. And that’s how I designed the integration.

The long list of sensors is managed via polling by the two rest sensors. The important information, like door and lock status get immediate status updates through callbacks. This is the best approach, because it follows what Nuki is doing and we also keep the polling calls at minimum, because the information of the extra sensors is not mission-critical.

I think now you can understand fully how I approached it. :slight_smile: