Skip to content

Unifi Access Point POE switching in HomeKit

In a previous post I wrote about my journey in making our home as energy efficient as possible. This blog post is another step in keeping guard on what’s consuming power, while you might not be using it: POE based WiFi access points.

Because working from home has become an adopted way of working, having good WiFi at home is a prerequisite for me. That’s why I have multiple access points:

  • One in our livingroom;
  • One in the home office;
  • One upstairs to cover the top floor;
  • And even one in the garden to work outside.

But a lot of the time, these device are actually doing nothing! One could suffice to keep the stuff running with a little bit less performance.

That’s why I wanted to have a script that is able selectively shutdown access points on request, and enable them easily when I want the best WiFi experience. But I also want to automate this, so when we are not at home, the not necessary access points shutdown.

In come the capabilities of my Unifi hardware. I can just stop the power over ethernet (poe) on my Unifi switch. But unfortunately that’s not enough. I also have one access point which facilitates a poe passthrough strategy. And also that one I want to independently control.

This means I have to control 2 different devices to setup the correct port state, and on top of that, the Unifi provided API doesn’t allow overriding the configuration of a single port at the time. With these 2 caveats in mind I managed to craft the following script to deal with these challenges.

#!/bin/bash

if [ $# -lt 3 ]; then
    echo "Usage : $0 port-nr state device"
    exit
fi

if [ "$3" = "uap" ]; then
   MAC=ma:co:fu:ap
else
   MAC=ma:co:fu:sw
fi

DEVICE=/tmp/device-$3.json
COOKIE=/tmp/cookie.txt
PORTS=/tmp/ports-$3.json
ID=0

if [ ! -f "$COOKIE" ]; then
    curl -X POST --insecure -H "Content-Type: application/json" -d '{
        "username": "user",
        "password": "password",
        "remember": true
    }' -c $COOKIE -o /dev/null -s https://ip-cloudkey:port/api/login
fi

if [ ! -f "$DEVICE" ]; then
    curl -X GET --insecure -b $COOKIE -s https://ip-cloudkey:port/api/s/default/stat/device/$MAC > $DEVICE
fi

if [ -f "$DEVICE" ]; then
    cat $DEVICE | jq "{port_overrides: .data[].port_overrides}" > $PORTS
    ID=$(cat $DEVICE | jq -r '.data[]._id')
fi

if [ -f "$PORTS" ]; then
    tmpfile=$(mktemp); cp $PORTS "$tmpfile" && jq --argjson PORT "$1" --arg MODE "$2" '.port_overrides[] |= (select(.port_idx==$PORT) |= (.poe_mode = $MODE))' "$tmpfile" > $PORTS && r
m -f "$tmpfile"
fi

sleep $((RANDOM % 10))
if [ -f "$DEVICE" ] && [ -f "$PORTS" ]; then
    curl -X PUT --insecure -H "Content-Type: application/json" -b $COOKIE -d @$PORTS -o /dev/null -s https://ip-cloudkey:port/api/s/default/rest/device/$ID
fi

rm -f $DEVICE
rm -f $PORTS
rm -f $COOKIE

So what does this script then do step by step

  1. It first validates the input, to test the arguments and understand which device we want to control
  2. Then it logs in the the Cloud Key using a user with admin privileges
  3. The script downloads the state of the selected device, or skips if the file still exists
  4. It extracts the ID & port overrides section of the device
  5. If the port overrides file exits, it does an in place edit of the file to set the new state of the port
  6. A very important random sleep, which allows me the call the script multiple times at once and because the in place editing of the port overrides file merge all the requested changes
  7. Send the changes to the identified device. Possibly multiple times, but if there is no change, the call will be silently ignored.

Expose POE switch in HomeKit?

I’m using Home Assistant to control my home. 2 integrations allow me to control the Access Points as switches in HomeKit.

  • HomeKit HA integration
  • HA default command line switching

This looks like this in the configuration.yml

switch:
  - platform: command_line
    switches:
      office_poe:
        friendly_name: Wifi Office
        command_on: "/bin/bash /config/script/poe-toggle.sh 6 auto usw"
        command_off: "/bin/bash /config/script/poe-toggle.sh 6 off usw"
        command_state: "/bin/bash /config/script/poe-state.sh 6 usw"
        value_template: '{{ value == "auto" }}'
      outside_poe:
        friendly_name: Wifi Outside
        command_on: "/bin/bash /config/script/poe-toggle.sh 1 passthrough uap"
        command_off: "/bin/bash /config/script/poe-toggle.sh 1 off uap"
        command_state: "/bin/bash /config/script/poe-state.sh 1 uap"
        value_template: '{{ value == "passthrough" }}'

With this configuration in place in Home Assistant you can expose the Access Points as switches in HomeKit, allowing you to toggle a Wifi Access Point on or off or add them to any form of automation you have in mind.

Now when we leave the house, or go to bed, only one access points remains on which saves 25 watts of energy consumption!

Resources

Leave a Reply

Your email address will not be published. Required fields are marked *