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