erikwihlborg76 / unofficial-danalock-web-api

9 stars 2 forks source link

Rate limit and configuration #4

Open schacka opened 5 months ago

schacka commented 5 months ago

Hi,

Thank you so much for implementing the Danalock Web Api! Finally I can link my camera to the door and unlock it ;)

I have two more suggestions: To use all functions in Home Assistant I have added the following configuration.yaml entries:

rest_command:
  <Your Lock Name lowercase>_lock:
    url: "http://nodered:1880/danalock/<Your Lock Name case-sensitive>/lock"
    method: get
    timeout: 20
  <Your Lock Name lowercase>_unlock:
    url: "http://nodered:1880/danalock/<Your Lock Name case-sensitive>/unlock"
    method: get
    timeout: 20  
  <Your Lock Name lowercase>_getstate:
    url: "http://nodered:1880/danalock/<Your Lock Name case-sensitive>/get-state"
    method: get
    timeout: 20
  <Your Lock Name lowercase>_getbattery:
    url: "http://nodered:1880/danalock/<Your Lock Name case-sensitive>/battery-level"
    method: get
    timeout: 20
rest:
  - resource: "http://nodered:1880/danalock/<Your Lock Name case-sensitive>/get-state"
    scan_interval: 3600 #Scan once every hour
    timeout: 30 #=> Update of 2 sensors at HA startup, rate limit of 1msg/10s + danalock web-api delay 
    binary_sensor:
      name: <Name like "Doorlock Status">
      unique_id : <Your Lock Name lowercase>_state
      device_class: lock
      value_template: >-
        {% if value == "Unlocked" %} on 
        {% elif value == "Locked" %} off 
        {% else %} unavailable {% endif %}
  - resource: "http://nodered:1880/danalock/{Your Lock Name case-sensitive}/battery-level"
    scan_interval: 86400 #Scan once every day
    timeout: 30 #=> Update of 2 sensors at HA startup, rate limit of 1msg/10s + danalock web-api delay 
    sensor:
      name: <Name like "Doorlock Battery Level">
      unique_id : <Your Lock Name lowercase>_battery
      device_class: battery
      unit_of_measurement: "%"
      value_template: '{{ int(value, 0) if is_number(int(value, 0)) else unavailable }}'
lock:
  - platform: template
    name: <Name like "Doorlock">
    unique_id : <Your Lock Name lowercase>
    # On/Off swapped for lock template compared to binary_sensor lock
    value_template: >-
      {% if is_state('binary_sensor.<Your Lock Name lowercase>_state',"off") %} on
      {% elif is_state('binary_sensor.<Your Lock Name lowercase>_state',"on") %} off 
      {% else %} unavailable {% endif %}
    lock:
      - service: rest_command.<Your Lock Name lowercase>_lock
        target:
          entity_id: binary_sensor.<Your Lock Name lowercase>_state
    unlock:
      - service: rest_command.<Your Lock Name lowercase>_unlock
        target:
          entity_id: binary_sensor.<Your Lock Name lowercase>_state

Using the above configuration the NodeRed endpoint is overloaded with multiple requests on Home Assistant startup (battery and state). A rate limit in NodeRed would prevent overloading. (see picture).

grafik

Cheers

erikwihlborg76 commented 5 months ago

Thanks for the feedback and suggested improvements!

Concurrency is tricky. I want to learn a bit more about the limitations of the danabridge for handling concurrent calls, and if node-red can support it gracefully without implementing throttling / rate limiting. For now that fix seems excellence though , thank you! 😊👍

I will also add the improvement you did to the home assistant config to this repo.

Thanks, Erik

schacka commented 5 months ago

Hi Erik,

I've tried things out for quite some time and finally decided to take a different approach, which I think works better. Maybe this will help others.

# source: https://github.com/gechu/unofficial-danalock-web-api
#dana actions and sensors
command_line:
  - sensor:
      command: "curl http://nodered:1880/danalock/<Your Lock Name case-sensitive>/battery-level"
      command_timeout: 30
      scan_interval: 86400
      name: <Name like "Doorlock Battery Level">
      unique_id : <Your Lock Name lowercase>_battery
      device_class: battery
      unit_of_measurement: "%"
  - binary_sensor:
      command: "curl http://nodered:1880/danalock/<Your Lock Name case-sensitive>/get-state"
      command_timeout: 30
      scan_interval: 3600
      name: <Name like "Doorlock Status">
      unique_id : <Your Lock Name lowercase>_state
      device_class: lock
      payload_on: "Unlocked"  # binary_sensor device_class lock works different
      payload_off: "Locked"
      icon: >
        {% if value == "Locked" %} mdi:door-closed-lock  
        {% elif value == "Unlocked" %} mdi:lock-open-variant
        {% else %} mdi:lock-off
        {% endif %}
  - switch:
      name: <Name like "Doorlock Action">
      unique_id : <Your Lock Name lowercase>_action
      command_on: "curl http://nodered:1880/danalock/<Your Lock Name case-sensitive>/lock"
      command_off: "curl http://nodered:1880/danalock/<Your Lock Name case-sensitive>/unlock"
      command_timeout: 30
# combine binary_sensor and switch to lock
lock:
  - platform: template
    name: <Name like "Doorlock">
    unique_id : <Your Lock Name lowercase>
    value_template: "{{ is_state('switch.<Your Lock Name lowercase>_state', 'off') }}" # binary_sensor to lock logic
    lock:
      service: switch.turn_on
      target:
        entity_id: switch.<Your Lock Name lowercase>_action
    unlock:
      service: switch.turn_off
      target:
        entity_id: switch.<Your Lock Name lowercase>_action
erikwihlborg76 commented 4 months ago

Hi @schacka and thanks again for sharing! Updating the HA configuration is next up on my todo list.

What is the benefit of using curl compared to the REST sensor?