UPDATED: Automating Unifi WiFi SSID password changes and QR code generation

Hi!

Just reviewed everything, watched video, and still get:

Error running command: /bin/bash /config/scripts/wifichange.sh change {{ username }} {{ password }} {{ baseurl }} {{ network_id }} {{ ssid }}, return code: 2

Can you help, please?

You’ve either not copied the code above correctly, or you’re not using a local user on the unifi system. Those would be my top guesses. Honestly, I’m not a *nix expert, so the exit codes are all but gibberish to me. All I can say for sure is if the instructions are followed exactly, the solution works as designed. Without seeing all the code exactly as you’ve entered it, any guess would be no better than throwing darts blindfolded (including my two guesses above LOL).

Thanks for answer.

It ends to be a Linux file format problem.

This solved it:

Excellent, glad to hear you got it working!

You could modify the original script to output a json file to your local www folder

SSID=${4}
PASS=${NEW_PWD}
QRTEXT="WIFI:T:WPA;S:${SSID};P:${PASS};;"

jq -n --arg qr_text "${QRTEXT}" '$ARGS.named' > ${SSID}_wifi.json

mv ${SSID}_wifi.json /config/www/${SSID}_wifi.json

This could then be read by a rest sensor in HA. This would serve as an entity containing a QR generation string for the qr-code-card. Assuming the SSID is Guest,

rest:
  - resource: http://127.0.0.1:8123/local/Guest_wifi.json
    scan_interval: 600
    sensor:
      - name: Guest Wifi
        value_template: "{{ value_json.qr_text }}"

Finally, whenever the automation runs, it too can be modified to call the homeassistant.update_entity service and update the sensor and thus the lovelace card with the current string

automation:
  - id: '1111111111111'
    alias: wifiPW
    description: ''
    mode: single
    trigger:
      - platform: time
        at: 03:00
    condition: []
    action:
      - service: shell_command.unifi_wlanchange
        data:
          username: !secret unifi-user
          password: !secret unifi-password
          baseurl: !secret unifi-baseurl
          network_id: !secret unifi-network-id
          ssid: !secret unifi-ssid
      # the delay is not strictly necessary,
      # but gives time for the json file to be written
      - delay: '00:00:10'
      - service: homeassistant.update_entity
        data:
          entity_id:
            - sensor.guest_wifi

[edit: updated automation with secrets]

1 Like

I achieved exactly this but with an alternative interration.
QR Codes Integration (qrcam) - Share your Projects! / Custom Integrations - Home Assistant Community (home-assistant.io)

where do I find the ip address for the still image url?

It’s the up address of whatever web server you out the qr code on. If you’re using my code without (much) modification, that would be your HA IP.

thank you …for some reason the automation isnt running the script …my password doesnt change for the wifi …could firewall rules block it from running …I made sure to create a new local admin user in unifi and tested the user name and password

I think your idea is really good.
I have implemented everything as you have described, but am slowly despairing.
I have the Unifi controller with version 7.3.83 as docker on a Unraid system.
The script also runs until the QR code is saved.
After that it should log on to the Unifi controller and change the password.
But what does not work.

Does anyone have the same problem or can help me?

Sorry, I don’t know if it works with the Unifi controller. This code was written and developed for a Dream Machine Pro…

That’s probably because the login & API endpoints for a UDM or UDM pro are different from the standard Unifi controller endpoints. You’ll need to make a few changes:

  1. Line 16: change https://${3}/api/auth/login to https://${3}/api/login
  2. Line 22: change https://${3}/proxy/network/api/s/default/rest/wlanconf/${4} to https://${3}/api/s/default/rest/wlanconf/${4}
  3. BaseURL: this script requires the format https://<ip-address>:<port>. Adjust the port to 8443 instead of 443 (UDM, UMD pro only). This assumes 8443 is mapped to 8443 in your Docker config.
1 Like

You’re the man! Thanks for the assist. :slight_smile:

Thanks @exx for you works !
I don’t have a UDM (PRO) but I was able to make it work by adapting the code with the indications of @rootnegativ1.
I’ll share the code here too if it can be useful to others.

Some explanations: according to the unifi wiki, I think it is useless to get the CSRF Token if you don’t have a UDM or a UDM Pro. I also took care to remove the change function to lighten the code. I also removed the EOF
in the configuration.yaml file, you have to use double quotes for the SSID of the WiFi, if ever there are SSID with the space character:

#!/bin/sh

cookie=$(mktemp)
headers=$(mktemp)

curl_cmd="curl --silent --output /dev/null --cookie ${cookie} --cookie-jar ${cookie} --insecure"

# generate new password
NEW_PWD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

# generate QR code
wget --output-document="/config/www/${5}.png" "http://api.qrserver.com/v1/create-qr-code/?data=WIFI:T:WPA;S:${5};P:${NEW_PWD};H:;&size=100x100"

# authenticate against unifi controller
${curl_cmd} -H 'Content-Type: application/json' -D ${headers} -d "{\"username\":\"${1}\", \"password\":\"${2}\"}" https://${3}/api/login

# change wifi password
${curl_cmd} -k -X PUT https://${3}/api/s/default/rest/wlanconf/${4} -H "Content-Type: application/json" -d "{\"_id\":\"${4}\",\"x_passphrase\":\"${NEW_PWD}\"}"

configuration.yaml:

shell_command:
    unifi_wlanchange: /bin/bash /config/scripts/wifichange.sh change {{ username }} {{ password }} {{ baseurl }} {{ network_id }} "{{ ssid }}"
1 Like

Excellent work!!! Glad to hear you were able to get it doing what you needed!!

If this was implemented in the UniFi integration, how would you prefer this to be exposed?

First, allow me to say how humbled I am that you would include a one-off feature that I (mostly) wrote into the main integration. I’m honored.

Beyond that, I’m not sure what the best way to expose it in the integration would be. I’m a pretty terrible UI developer, just ask anyone who’s seen my dashboard… Lol

That aside, perhaps another screen added to the config wizard that has a checkbox for if you want to do this or not, then a box for the time you want it to happen, and then perhaps a drop down for the SSID you want to do this to? It would then create a camera entity named like “myssid_qrcode_camera” or something that users could then add to their dashboard? I suppose you’d also need another input field for how many characters they wanted it to be, and perhaps one for if they want special characters included (some devices have trouble, though I’m not sure that would be applicable in this instance?) Not sure. Just spitballing. I’m sure you will come up with something excellent. :slight_smile:

Thanks again, this is just too cool!

1 Like

you could do it in two parts:

  1. create a camera entity for each wlan which includes some of the class attributes from aiounifi including _id, name, and x_passphrase. Then use the python module qrcode to generate a png for the camera. Not really sure where to store the png file…
  2. create a service called unifi.set_wifi_password
    Service data attribute Optional Description
    id no 24 character string identifying the wireless network
    random no BOOLEAN should the password be randomized
    password yes STRING user provided password
    if random is set true, then override any user provided password with one that is randomly generated. This could simply be a bunch of random characters, or something like Diceware passphrases using the python module xkcdpass
1 Like

I don’t think it’s a one-off feature, it provides real value. Being done through alternative means than an official integration doesn’t diminish the value you’ve provided here!

1 Like

Thanks, yes I was thinking something similar.

Great suggestions on the service however I ponder if its unnecessarily complex adding a service for this rather than just a button to set a new randomised password, the whole thing with the QR code is to not need to know the password right?

1 Like