GPIO LED control

You could use a hotplug.d script on the network interface (/etc/hotplug.d/net), but for something like this I think a procd service script makes more sense as it should give you more control of the process. In particular you’ll want to make sure the service has appropriate triggers to restart when the AP is reconfigured.

For information on procd service scripts please take a look at:

[OpenWrt Wiki] procd init scripts - for general information on procd scripts
[OpenWrt Wiki] Create a sample procd init script - for a sample procd script

I have written a procd script in the past which watches the wireless configuration and runs a program if the desired interface is configured as an AP. I’ve modified this script to call the hostapd_cli program with your action script. Install this script as /etc/init.d/hostap-leds on the device. It should start on boot, and whenever a change is made to /etc/config/wireless or uci wireless any subsequent reload will stop and restart the service.

Note that we do not need to pass in the -B parameter to hostapd_cli_s1g here as procd scripts expect programs to run in the foreground (procd daemonises them for you). This allows redirection of stdout and stderr to the syslog, which you will be able to query with logread -e hostap-leds.

Note that I haven’t strictly tested this script as is. It is very lightly modified from a script which I know works. So I’m fairly confident it should get you most of the way forward.

#!/bin/sh /etc/rc.common

. /lib/netifd/netifd-wireless.sh

START=99
STOP=10

USE_PROCD=1
PROG=/sbin/hostapd_cli_s1g
ACTION_SCRIPT=/lib/functions/clientconnected.sh
SERVICE=hostap-leds

get_first_ifname() {
        [ -n "$ifname" ] && return
        json_get_vars ifname
        json_select config
        json_get_values networks "network"
        json_select ..
}

wait_for_ifname() {
        local radio=$1
        local delay=${2-5}
        local timeout=60

        local start_time="$(date -u +%s)"
        local end_time=
        local elapsed=

        while true; do
                json_load "$(wifi status $radio)"
                json_select $radio
                for_each_interface "ap" get_first_ifname
                [ -n "$ifname" ] && return 0;

                end_time="$(date -u +%s)"
                elapsed="$(($end_time-$start_time))"
                if [ "$elapsed" -gt "$timeout" ]; then
                        return 1
                fi

                sleep $delay
        done
}

start_cli() {
        local cfg="$1"
        local radio=$cfg
        config_get_bool enabled "$cfg" 'dcs' 0
        [ $enabled -ne 1 ] && return

        config_get type "$cfg" 'type'
        if [ "$type" != "morse" ]; then
                logger -t $SERVICE -p daemon.crit "wireless.${cfg} not a morse device!"
                return 1
        fi

        radiojs=$(wifi status $radio 2>/dev/null)
        if [ $? -ne 0 ]; then
                logger -t $SERVICE -p daemon.crit "Selected radio $radio does not exist!"
                return 1
        fi

        json_load "$radiojs"
        json_select $radio
        json_get_vars disabled
        set_default disabled 1
        if [ "$disabled" -ne 0 ]; then
                logger -t $SERVICE -p daemon.crit "$radio disabled"
                return 1
        fi

        ifname=
        networks=
        if ! wait_for_ifname $radio; then
                logger -t $SERVICE -p daemon.crit "Couldn't get ifname for ap on $radio"
                return 1
        fi

        procd_open_instance $cfg.$ifname
        procd_set_param command $PROG -i "$ifname" -a $ACTION_SCRIPT
        procd_set_param file $ACTION_SCRIPT
        procd_set_param netdev "$ifname"
        procd_set_param stdout 1
        procd_set_param stderr 1
        procd_set_param respawn
        procd_close_instance
}

start_service() {
        config_load wireless
        config_foreach start_cli wifi-device
}

service_triggers() {
        procd_add_reload_trigger wireless
        procd_add_reload_interface_trigger $networks
}