Cookie login to get value for sensor

Greetings,

Please help with the correct approach to the followng task: I need to make sensor, which value is taken from a remote resourse via HTTP GET method. The problem is that first I need to login to this resourse (with POST), get the cookie, then use this cookie to GET required data.

As far as I understrand, its impossible to do it with a single command for REST sensor, so i need to write a python script to do several HTTP requests and invoke this script from the Command line sensor. After i tried official python_scripts integration, it turned out that it does not support import requests, so I tried unofficial pyscript integration. It still doesn’t work, only during initialisation. I asked at this at pyscript topic: Pyscript - new integration for easy and powerful Python scripting - #181 by Vsider , but no answer there, I now think that maybe pyscript is not intended such use and I probably took the wrong way in the very beginning.

Unfortunately, I couldn’t find similar solutions on this forum and would appreciate a hint.

Node red has a basic authentication in its http request, but if it works on your site I do not know.
Does the site not have an API, maybe?

Can you tell us what site it is?

Sure, I’m trying to access unifi controller API, but it has no API-key authentification, it requires cookie login, here is description of API:
https://ubntwiki.com/products/software/unifi-controller/api

What sensor value are you trying to extract?

Several, but lets take an example: the value is parameter update_available in seciton <MYURL>api/s/default/stat/sysinfo.
So if you try simply get without login you’ll get the following:

{"meta":{"rc":"error","msg":"api.err.LoginRequired"},"data":[]}

If you login first, according to the instructions from my link, get the cookie and try to get the json data with this with cookie - you get the data you need and can extract required value, but the problem is to implement several HTTP requests in Home assistant sensor, so that the sensor (in this case binary sensor) becomes true when the update is actually available.

I just wondered if the same values were not present on your devices too, so you could extract them through SMNP, but if they are not then either Node-Red or a bash script might be the solution.

As per @WallyR I would use a bash script for this

Hello, I want to caputre only one value in the cookie in the request header. I have modify my sensor configuration to capture the cookie .liteblue

@Vsider

I spent the weekend scratching my head over this. I didn’t want any scripts with dependencies or cli utilities, I just wanted to access the damn api

I came up with this (cookie in variable)

data='{"username":"user","password":"pass"}'; ip='https://192.168.1.1:443'; c=$(curl -H 'Content-Type: application/json' -d $data -ksc - $ip/api/auth/login -o /dev/null); echo "${c}" | curl -ksb - $ip/proxy/network/api/s/default/stat/device/

BUT because of the limitations of Command line Sensor, with no json_attributes_path, the only attribute that works is data and the sensor gets huge

So I’m using | as a delimiter instead

sensor:
  - platform: command_line
    name: udm_unifios
    command: |-
      data='{"username":"user","password":"pass"}'; ip='https://192.168.1.1:443';\
      c=$(curl -H 'Content-Type: application/json' -d $data -ksc - $ip/api/auth/login -o /dev/null);\
      echo "${c}" | curl -ksb - $ip/proxy/network/api/s/default/stat/device/
    value_template: |-
      {% set json = value_json.data[0] %}
      {{ json["system-stats"].cpu }}|
      {{ json.temperatures[1].value | round(1) }}|
      {{ json["system-stats"].mem }}|
      {{ ((json.storage[1].used / json.storage[1].size) * 100) | round(1) }}|
      {{ json.internet }}|
      {{ json.startup_timestamp | timestamp_custom('%Y-%m-%dT%H:%M:%S') }}|
      {{ json.displayable_version }}|
      {{ json.upgradable }}
    scan_interval: 60

template:
  binary_sensor:
    - unique_id: udm_internet
      icon: mdi:wan
      device_class: connectivity
      state: >
        {{ states('sensor.udm_unifios').split('|\n')[4] | default }}
      attributes:
        friendly_name: Internet

    - unique_id: udm_upgradable
      icon: mdi:update
      device_class: update
      state: >
        {{ states('sensor.udm_unifios').split('|\n')[7] | default }}
      attributes:
        friendly_name: Uppdatering

  sensor:
    - unique_id: udm_cpu
      icon: mdi:chip
      unit_of_measurement: '%'
      state: >
        {{ states('sensor.udm_unifios').split('|\n')[0] | default }}
      attributes:
        friendly_name: Processor

    - unique_id: udm_cpu_temp
      icon: mdi:thermometer
      unit_of_measurement: '°C'
      state: >
        {{ states('sensor.udm_unifios').split('|\n')[1] | default }}
      attributes:
        friendly_name: Processortemperatur

    - unique_id: udm_mem
      icon: mdi:memory
      unit_of_measurement: '%'
      state: >
        {{ states('sensor.udm_unifios').split('|\n')[2] | default }}
      attributes:
        friendly_name: Minne

    - unique_id: udm_disk
      icon: mdi:harddisk
      unit_of_measurement: '%'
      state: >
        {{ states('sensor.udm_unifios').split('|\n')[3] | default }}
      attributes:
        friendly_name: Lagring

    - unique_id: udm_uptime
      device_class: timestamp
      state: >
        {{ states('sensor.udm_unifios').split('|\n')[5] | default }}
      attributes:
        friendly_name: Senaste omstart

    - unique_id: udm_version
      icon: mdi:router-wireless
      state: >
        {{ states('sensor.udm_unifios').split('|\n')[6] | default }}
      attributes:
        friendly_name: Version
6 Likes

@Mattias_Persson
Incredible, that’s exactly the solution what I was looking for. Thanks, mate! :+1:
The only thing I added is this line at the end of command:

echo "${c}" | curl -ksb - $ip/api/logout

Not really necessary, but seems logical.

Is this still working?

I tried but get no sensors :frowning:

Give this a try:

command_line:
  - sensor:
      name: Unifi Device
      command: 'curl -o /dev/null -H ''Content-Type: application/json'' -d ''{"username": "un", "password": "pw"}'' -ks https://x.x.x.x/api/auth/login -c cookies.txt && curl -ks https://x.x.x.x/proxy/network/api/s/default/stat/device -b cookies.txt'
      value_template: "{{ 'OK' }}"
      json_attributes:
        - data
      scan_interval: 30

and then

template:
  - name: "UDM Processor Use"
    state: >
      {% set items = state_attr('sensor.unifi_device', 'data') %}
      {% for x in items %}
        {% if (x['type'] == 'udm') %}
          {{ x['system-stats']['cpu'] | round(1) }}
        {% endif %}
      {% endfor %}
    unit_of_measurement: "%"
    state_class: measurement
    icon: mdi:cpu-64-bit

etc.