Sorry to be ignorant, but programmatically, where would that enable command be put to automatically enable it? And how do the others in init.d get started?
Actually, I put āservice hostap-leds enableā in /etc/rc.local and that seemed to start hostap-leds. I see the logread messages I put in there for the file and start of each function. However, when the client connected or disconnected, the clientconnected.sh did not get run. I have log messages in that, too, per previous note. I see those when I conn/disc if I run the āhostapd_cli_s1g -i wlan0 -a /lib/functions/clientconnected.shā in the console (shell), but not from the service enable in rc.local.
Note the āhostap-ledsā items in the log below. Lines that say āhostap-leds launchedā is at the top of the āhostap-ledsā file.
Thu Dec 12 14:47:43 2024 user.notice -p: daemon.crit hostap-leds launched...
Thu Dec 12 14:47:44 2024 daemon.notice netifd: lan (3013): udhcpc: broadcasting discover
Thu Dec 12 14:47:44 2024 daemon.notice netifd: lan (3013): udhcpc: broadcasting select for 192.168.1.2, server 192.168.1.1
Thu Dec 12 14:47:44 2024 daemon.notice netifd: lan (3013): udhcpc: lease of 192.168.1.2 obtained from 192.168.1.1, lease time 86400
Thu Dec 12 14:47:44 2024 daemon.crit hostap-leds: hostap-leds start_service()...
Thu Dec 12 14:47:44 2024 daemon.crit hostap-leds: hostap-leds start_cli()...
Thu Dec 12 14:47:44 2024 daemon.crit hostap-leds: hostap-leds start_cli()...
Thu Dec 12 14:47:44 2024 daemon.crit hostap-leds: hostap-leds service_triggers()...
Thu Dec 12 14:47:44 2024 daemon.notice hostapd: Set new config for phy phy0:
Thu Dec 12 14:47:45 2024 daemon.notice netifd: Interface 'lan' is now up
Thu Dec 12 14:47:45 2024 daemon.notice netifd: Wireless device 'radio0' is now up
Thu Dec 12 14:47:45 2024 user.notice -p: daemon.crit hostap-leds launched...
Thu Dec 12 14:47:46 2024 kern.info kernel: [ 65.452021] Resetting Morse Chip
Thu Dec 12 14:47:46 2024 kern.info kernel: [ 65.478498] Done
Thu Dec 12 14:47:46 2024 user.notice root: Prplmesh is disabled
Thu Dec 12 14:47:46 2024 kern.info kernel: [ 65.628760] morse_sdio mmc0:0001:1: sdio removed func 1 vendor 0x325b device 0x306
Thu Dec 12 14:47:46 2024 kern.info kernel: [ 65.644719] mmc0: card 0001 removed
Thu Dec 12 14:47:46 2024 kern.info kernel: [ 65.713854] mmc0: new high speed SDIO card at address 0001
Thu Dec 12 14:47:46 2024 kern.debug kernel: [ 65.725085] mmcblk mmc0:0001: no of_node; not parsing pinctrl DT
Thu Dec 12 14:47:46 2024 user.notice HOTPLUG: 05-getapipaddr ****** 'ifup' - device:'br0' interface:'lan' ******
I really should have tested the script before sharing it! Thereās a few lines in the start_cli
function which are definitely going to cause premature exit as they are looking for a configuration option you likely have not enabled. These lines are artefacts of me modifying a previous script - I must have just missed them.
Please remove
config_get_bool enabled "$cfg" 'dcs' 0
[ $enabled -ne 1 ] && return
from the start_cli()
function in the procd script. Reboot or service hostap-leds restart
once the changes are saved.
Bingo!! That worked, Arien. Thanks so much! And I left āservice hostap-leds enableā in /etc/rc.local. I suspect you donāt need to put āservice hostap-leds startā right after that, since it worked with just the enable. Correct?
I still need to finish addressing the issue of a client finding AP ip addr I raised in another thread. Iāll reply to that one specifically as needed, not here.
Arien - question for you on this. I have the hostap-leds in /etc/init.d as discussed above. Works great on the AP. However, the client doesnāt necessarily like having this. When I disable halow radio, it takes about 70 sec for the system to finally getting around to when it shows the line in the log ādaemon.notice netifd: Interface āahwlanā is disabledā. Without hostap-leds in the image when running as client, it is fairly quick and that is done in 11 sec after disabling halow radio in luci, which from what Iāve seen before is typical.
Question is: what should I use to not have hostap-leds do anything if itās running on a client?
Somewhere else in my code, after the device is setup as ap or client through the wizard, Iāve checked wireless.default_radio1.mode. If itās āstaā, itās client; if āapā, itās ap and Iāve acted accordingly in that other code. And if you havenāt run the wizard, that param is not even there. In this case, if Iām looking to use hostap-leds do what it does, that parameter must exist and be an āapā.
What would you recommend as the best way to check this so it only does the hostap-leds if the device is ap?
Recall that post above about /lib/functions/clientconnected.sh with the /etc/init.d/hostap-leds hook for the timeout when a client goes away ungracefully? It works great, as i know when that happens. However, in the disconnected path of that sh, I was hoping it would allow me to change the led at that time. But, before clientconnected.sh exits, I call the routine (set_ap_halow_led) that checks if ANY clients are attached to know how to set the led. In this condition, since itās still in the disconnected path before exiting, this client is still in the assoclist so the led doesnāt change until the cron I have setup to check every minute triggers again. Then, itās then that timer fires to do āiwinfo wlan0 assoclistā, that it shows āNo station connectedā. I suspect itās the timing of when hostap-leds hits that clientconnected.sh that it does that before the client is actually out of the assoclist. However, if I do the graceful disconnect by disabling the halow radio in network/wireless in luci, the same routine (set_ap_halow_led) works fine. If this was windows, which Iām so much more familiar with, I could do a pump loop to process events which could allow processing things when youāre in a thread. Does this make sense? Iām wondering how to deal with this in this openwrt linux? Ideas?
Question is: what should I use to not have hostap-leds do anything if itās running on a client?
In order to get the Linux interface name from the UCI configuration, the script has to wait_for_ifname()
which expects an ap to exist. Unfortunately, there is asynchronicity here and it can take some time between when this script is started after a wireless configuration change, to when a Linux interface is actually brought up. This script is a little naive, and just performs a busy loop with a 60 second timeout before it will fail. A slightly better design may have been to push the timeout into the procd command itself to prevent procd from blocking, however we would then lose the netdev
parameter which would mean the service wonāt restart on any changes to the interface.
So continuing with the naive design, you definitely want a check in start_cli()
to ensure there is an AP configured on the device before running this script. Hereās an updated procd script which again, I havenāt tested. Note that Iāve changed start_service to iterate over the configured list of wifi-iface
instead of wifi-device
as it does simplify this check a bit. We can also better filter for the ifname.
#!/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
wait_for_ifname() {
local radio=$1
local iface=$2
local delay=${3-5}
local timeout=60
local start_time="$(date -u +%s)"
local end_time=
local elapsed=
while true; do
wifi status "$radio" | jsonfilter -e '@.*.interfaces[@.section="$iface"].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"
config_get mode "$cfg" mode
if [ "$mode" != "ap" ]; then
logger -t $SERVICE -p daemon.debug "wireless.${cfg} not an ap interface"
return 1
fi
config_get radio "$cfg" device
config_get type "$radio" 'type'
if [ "$type" != "morse" ]; then
logger -t $SERVICE -p daemon.crit "wireless.${radio} 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 $cfg; then
logger -t $SERVICE -p daemon.crit "Couldn't get ifname for $cfg on $radio"
return 1
fi
procd_open_instance $radio.$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-iface
}
service_triggers() {
procd_add_reload_trigger wireless
procd_add_reload_interface_trigger $networks
}
before clientconnected.sh exits, I call the routine (set_ap_halow_led) that checks if ANY clients are attached to know how to set the led. In this condition, since itās still in the disconnected path before exiting, this client is still in the assoclist so the led doesnāt change until the cron I have setup to check every minute triggers again. Then, itās then that timer fires to do āiwinfo wlan0 assoclistā, that it shows āNo station connectedā.
Interesting that the client is still in the list during the AP_STA_DISCONNECTED event. Can you run hostapd_cli all_sta
and iwinfo wlan0 assoclist
during this event so we can examine if there is a difference? Itās possible that during the non-graceful disconnect hostap has registered the station leaving, but it hasnāt been propagated to underlying mac80211 layer yet and so iwinfo
is still seeing the stations through netlink.
Hi, Arien. Question for you here.
When I factory reset then setup the client then ap using default ssid, I set the ap to be a bridge. Obviously it should be connected to a dhcp router which would assign the ap and client their ip addresses. This works perfectly fine when I switch the cable on the ap from the laptop to the router as soon as I click to leave the ap wizard. Then, the process of it getting a new i/f due to the router runs through that script you last gave me and my blue led on the ap turns on immediately since it goes through that clientconnected.sh script when the client halow connects.
However, if I donāt connect the router after the wizard, it doesnāt run through the hostap-leds script to setup the trigger to clientconnected.sh. I have checks in that script below to only do start_cli(), start_service() and service_triggers() if it is an ap. Before I connect the router, those routines show: āthis is not an apā. Thus, this script doesnāt activate to turn the ap blue led on immediately when thereās a client halow connect.
This is a non-issue when this is setup as ap router, but I want to cover the base that if this is setup as ap bridge and either a router doesnāt exist or something happens to the router (i.e. say facility power loss that knocks out the router but our devices still work), that ap blue led will still work as we desire. That means another way to activate this script so it knows this is an ap after the wizard is complete, but not rely on the router connection.
Iām trying to figure out a good spot to put this to accomplish this. What would you suggest?
top of script. Note what's added to rc.local:
#this is used to replace the command "hostapd_cli_s1g -i wlan0 -a /lib/functions/clientconnected.sh"
#this is enabled and started in /etc/rc.local, which does stuff after boot done
#the commands there are: "service hostap-leds enable" and "service hostap-leds start"
logger -t $SERVICE -p daemon.crit "hostap-leds launched..."
:
:
start_cli() {
logger -t $SERVICE -p daemon.crit "hostap-leds start_cli()..."
#Only do if radio is 'ap'. Since this is run before wizard after image loaded,
#when device set as ap after wizard, reboot to run this as an ap unless we
#know where to put something after wizard to make this service restart
result=$(uci show wireless.default_radio1.mode | grep "'ap'")
if [ ! -z "$result" ]; then
isap=1
fi
if [ $isap -eq 1 ]; then
:
Do this routine as provided
:
else
logger -t $SERVICE -p daemon.crit "hostap-leds start_cli()...THIS IS NOT AN AP!!!"
fi
}
start_service() {
logger -t $SERVICE -p daemon.crit "hostap-leds start_service()..."
#Only do if radio is 'ap'. Since this is run before wizard after image loaded,
#when device set as ap after wizard, reboot to run this as an ap unless we
#know where to put something after wizard to make this service restart
result=$(uci show wireless.default_radio1.mode | grep "'ap'")
if [ ! -z "$result" ]; then
isap=1
fi
if [ $isap -eq 1 ]; then
config_load wireless
config_foreach start_cli wifi-device
else
logger -t $SERVICE -p daemon.crit "hostap-leds start_service()...THIS IS NOT AN AP!!!"
fi
}
service_triggers() {
logger -t $SERVICE -p daemon.crit "hostap-leds service_triggers()..."
#Only do if radio is 'ap'. Since this is run before wizard after image loaded,
#when device set as ap after wizard, reboot to run this as an ap unless we
#know where to put something after wizard to make this service restart
result=$(uci show wireless.default_radio1.mode | grep "'ap'")
if [ ! -z "$result" ]; then
isap=1
fi
if [ $isap -eq 1 ]; then
procd_add_reload_trigger wireless
procd_add_reload_interface_trigger $networks
else
logger -t $SERVICE -p daemon.crit "hostap-leds service_triggers()...THIS IS NOT AN AP!!!"
fi
}
Arien, I actually put āservice hostapd-leds restartā in /etc/hotplug.d/ieee80211/10-wifi-detect" and it seemed to work. That file is:
#!/bin/sh
echo "10-wifi-detect action: ${ACTION} - device:'$DEVICENAME' interface:'$INTERFACE'" > /dev/console
logger -t HOTPLUG -s "****** 10-wifi-detect '$ACTION' - device:'$DEVICENAME' interface:'$INTERFACE' ******"
[ "${ACTION}" = "add" ] && {
#default from original file
/sbin/wifi config
basename "$(readlink -f "/sys/${DEVPATH}/device/driver")" | grep '^morse_' || return;
phy=${DEVPATH##*/}
[ -n $phy ] || exit 0
echo "${phy}assoc" > /sys/class/leds/blue:sys/trigger
echo "${phy}assoc" > /sys/class/leds/red:sys/trigger
logger -t HOTPLUG -s "${phy}assoc"
echo "New assoc: ${phy}assoc" > /dev/console
service hostap-leds restart
}
[ "${ACTION}" = "remove" ] && {
#echo "clear blue, red led trigger to none" > /dev/console
echo "none" > /sys/class/leds/blue:sys/trigger
echo "none" > /sys/class/leds/red:sys/trigger
}
It appears youāve found a fairly valid solution of giving the service a kick when the interface comes up.
Iāll take a look at spinning it all up myself and see if I have any alternative suggestions. The procd service itself should work when the device is in bridge mode.
What may be going wrong is the configuration set before entering bridge mode is such that the service hasnāt correctly registered the service triggers.
Was it also failing before you added the if
statements to the service_triggers()
function? I would encourage leaving the service_triggers present in all modes, and just handle the ap check early in the start_service()
, that way procd can be left responsible for kicking the service.