diff --git a/ffac-ssid-changer/files/lib/gluon/ssid-changer/ssid-changer.sh b/ffac-ssid-changer/files/lib/gluon/ssid-changer/ssid-changer.sh deleted file mode 100755 index 58b2e0bb..00000000 --- a/ffac-ssid-changer/files/lib/gluon/ssid-changer/ssid-changer.sh +++ /dev/null @@ -1,154 +0,0 @@ -#!/bin/sh - -################# -# safety checks # -################# -log_debug() { - if [ "${SETTINGS_DEBUG_LOGGING}" = "1" ]; then - logger -t "ffac-ssid-changer" -p debug "$@" - fi -} - -safety_exit() { - log_debug "$1, exiting with error code 2" - exit 2 -} -SETTINGS_DEBUG_LOGGING="$(uci -q get ssid-changer.settings.debug_log_enabled)" -: "${SETTINGS_DEBUG_LOGGING:="0"}" - -pgrep -f autoupdater >/dev/null && safety_exit 'autoupdater running' -UT=$(sed 's/\..*//g' /proc/uptime) -[ "$UT" -gt 60 ] || safety_exit 'less than one minute' -[ "$(find /var/run -name "hostapd-*" | wc -l)" -gt 0 ] || safety_exit 'no hostapd-*' - -# only once every timeframe minutes the SSID will change to the Offline-SSID -# (set to 1 minute to change immediately every time the router gets offline) -MINUTES="$(uci -q get ssid-changer.settings.switch_timeframe)" -: "${MINUTES:=30}" - -# the first few minutes directly after reboot within which an Offline-SSID always may be activated -# (must be <= switch_timeframe) -FIRST="$(uci -q get ssid-changer.settings.first)" -: "${FIRST:=5}" - -# the Offline-SSID will start with this prefix use something short to leave space for the nodename -# (no '~' allowed!) - -PREFIX="$(uci -q get ssid-changer.settings.prefix)" -: "${PREFIX:=FF_Offline_}" - -if [ "$(uci -q get ssid-changer.settings.enabled)" = '0' ]; then - DISABLED='1' -else - DISABLED='0' -fi - -# generate the ssid with either 'nodename', 'mac' or to use only the prefix set to 'none' -SETTINGS_SUFFIX="$(uci -q get ssid-changer.settings.suffix)" -: "${SETTINGS_SUFFIX:=nodename}" - -if [ "$SETTINGS_SUFFIX" = 'nodename' ]; then - SUFFIX="$(uname -n)" - # 32 would be possible as well - if [ ${#SUFFIX} -gt $((30 - ${#PREFIX})) ]; then - # calculate the length of the first part of the node identifier in the offline-ssid - max_suffix_length=$(( (28 - ${#PREFIX} ) / 2 )) - # use the first and last part of the nodename for nodes with long name - suffix_first_chars="$(printf '%s' "$SUFFIX" | head -c ${max_suffix_length})" - suffix_last_chars="$(printf '%s' "$SUFFIX" | tail -c ${max_suffix_length})" - SUFFIX="${suffix_first_chars}...${suffix_last_chars}" - fi -elif [ "$SETTINGS_SUFFIX" = 'mac' ]; then - SUFFIX="$(uci -q get network.bat0.macaddr | /bin/sed 's/://g')" -else - # 'none' - SUFFIX='' -fi - -OFFLINE_SSID="$PREFIX$SUFFIX" - -# temp file to count the offline incidents during switch_timeframe -TMP=/tmp/ssid-changer-count -if [ ! -f $TMP ]; then echo "0">$TMP; fi -OFF_COUNT=$(cat $TMP) - -TQ_LIMIT_ENABLED="$(uci -q get ssid-changer.settings.tq_limit_enabled)" -# if true, the offline ssid will only be set if there is no gateway reachable -# upper and lower limit to turn the offline_ssid on and off -# in-between these two values the SSID will never be changed to prevent it from toggling every Minute. -: "${TQ_LIMIT_ENABLED:=0}" - -if [ "$TQ_LIMIT_ENABLED" = 1 ]; then - TQ_LIMIT_MAX="$(uci -q get ssid-changer.settings.tq_limit_max)" - # upper limit, above that the online SSID will be used - : "${TQ_LIMIT_MAX:=45}" - TQ_LIMIT_MIN="$(uci -q get ssid-changer.settings.tq_limit_min)" - # lower limit, below that the offline SSID will be used - : "${TQ_LIMIT_MIN:=35}" - # grep the connection quality of the currently used gateway - GATEWAY_TQ=0 - if [ -f /var/gluon/state/has_default_gw4 ]; then - GATEWAY_TQ="$(batctl gwl -H | grep -e "^\*" | awk -F'[()]' '{print $2}' | tr -d " ")" - fi - - MSG="TQ is $GATEWAY_TQ, " - - if [ "$GATEWAY_TQ" -ge "$TQ_LIMIT_MAX" ]; then - CHECK=1 - elif [ "$GATEWAY_TQ" -lt "$TQ_LIMIT_MIN" ]; then - CHECK=0 - else - # this is just get a clean run if we are in-between the grace period - log_debug "TQ is $GATEWAY_TQ, do nothing" - exit 0 - fi -else - MSG="" - if [ -f /var/gluon/state/has_default_gw4 ]; then - CHECK=1 - else - CHECK=0 - fi -fi - -UP=$((UT / 60)) -M=$((UP % MINUTES)) - -if [ "$CHECK" -gt 0 ] || [ "$DISABLED" = '1' ]; then - log_debug "$MSG node is online" - uci revert wireless - wifi reconf -elif [ "$CHECK" -eq 0 ]; then - log_debug "$MSG node is considered offline" - if [ $UP -lt "$FIRST" ] || [ $M -eq 0 ]; then - # set SSID offline, only if uptime is less than FIRST or exactly a multiplicative of switch_timeframe - if [ $UP -lt "$FIRST" ]; then - T=$FIRST - else - T=$MINUTES - fi - #echo minute $M, check if $OFF_COUNT is more than half of $T - if [ "$OFF_COUNT" -ge $((T / 2)) ]; then - # node was offline more times than half of switch_timeframe (or than $FIRST) - OWE0="$(uci -q get wireless.owe_radio0.ssid)" - [ -n "$OWE0" ] && uci set wireless.owe_radio1.enabled=0 - OWE1="$(uci -q get wireless.owe_radio1.ssid)" - [ -n "$OWE1" ] && uci set wireless.owe_radio1.enabled=0 - CLIENT0="$(uci -q get wireless.client_radio0.ssid)" - [ -n "$CLIENT0" ] && uci set wireless.client_radio0.ssid="$OFFLINE_SSID" - CLIENT1="$(uci -q get wireless.client_radio1.ssid)" - [ -n "$CLIENT1" ] && uci set wireless.client_radio1.ssid="$OFFLINE_SSID" - CLIENT2="$(uci -q get wireless.client_radio2.ssid)" - [ -n "$CLIENT2" ] && uci set wireless.client_radio2.ssid="$OFFLINE_SSID" - - wifi reconf - fi - #else echo minute $M, just count $OFF_COUNT - fi - echo "$((OFF_COUNT + 1))">$TMP -fi - -if [ $M -eq 0 ]; then - # set counter to 0 if the timeframe is over - echo "0">$TMP -fi diff --git a/ffac-ssid-changer/files/usr/lib/micron.d/ssid-changer b/ffac-ssid-changer/files/usr/lib/micron.d/ssid-changer index e3a99fa4..1c76b6ef 100644 --- a/ffac-ssid-changer/files/usr/lib/micron.d/ssid-changer +++ b/ffac-ssid-changer/files/usr/lib/micron.d/ssid-changer @@ -1 +1 @@ -* * * * * /lib/gluon/ssid-changer/ssid-changer.sh +* * * * * /lib/gluon/ssid-changer/ssid-changer.lua diff --git a/ffac-ssid-changer/luasrc/lib/gluon/ssid-changer/ssid-changer.lua b/ffac-ssid-changer/luasrc/lib/gluon/ssid-changer/ssid-changer.lua new file mode 100755 index 00000000..3121ac31 --- /dev/null +++ b/ffac-ssid-changer/luasrc/lib/gluon/ssid-changer/ssid-changer.lua @@ -0,0 +1,183 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() + +-- Safety check functions +local function log_debug(...) + if uci:get('ssid-changer', 'settings', 'debug_log_enabled') == '1' then + os.execute('logger -t "ffac-ssid-changer" -p debug "' .. table.concat({...}, ' ') .. '"') + end +end + +local function safety_exit(message) + log_debug(message .. ", exiting with error code 2") + os.exit(2) +end + +-- Check if the script is enabled +if uci:get('ssid-changer', 'settings', 'enabled') == '0' then + os.exit(0) -- Exit silently if the script is disabled +end + +-- Check for autoupdater running +local function is_autoupdater_running() + local handle = io.popen('pgrep -f autoupdater') + local result = handle:read("*a") + handle:close() + return result ~= '' +end + +if is_autoupdater_running() then + safety_exit('autoupdater running') +end + +-- Read uptime +local function get_uptime() + local file = io.open('/proc/uptime', 'r') + local uptime = file:read("*n") -- Read only the first number (uptime in seconds) + file:close() + return uptime +end + +local uptime = get_uptime() +local uptime_minutes = math.floor(uptime / 60) +local monitor_duration = tonumber(uci:get('ssid-changer', 'settings', 'switch_timeframe') or 30) +local is_switch_time = uptime_minutes % monitor_duration + +if uptime < 60 then + safety_exit('uptime less than one minute') +end + +-- Check for hostapd processes +local function has_hostapd_processes() + local handle = io.popen('find /var/run -name "hostapd-*.conf" | wc -l') + local result = handle:read("*a") + handle:close() + return tonumber(result) > 0 +end + +if not has_hostapd_processes() then + safety_exit('no hostapd-*') +end + +-- Generate the offline SSID +local function calculate_offline_ssid() + local prefix = uci:get('ssid-changer', 'settings', 'prefix') or 'FF_Offline_' + local settings_suffix = uci:get('ssid-changer', 'settings', 'suffix') or 'nodename' + local suffix + + if settings_suffix == 'nodename' then + suffix = io.popen('uname -n'):read("*a"):gsub("%s+", "") + if #suffix > (30 - #prefix) then + local max_suffix_length = math.floor((28 - #prefix) / 2) + local suffix_first_chars = suffix:sub(1, max_suffix_length) + local suffix_last_chars = suffix:sub(-max_suffix_length) + suffix = suffix_first_chars .. '...' .. suffix_last_chars + end + elseif settings_suffix == 'mac' then + suffix = io.popen('uci -q get network.bat0.macaddr | sed "s/://g"'):read("*a"):gsub("%s+", "") + else + suffix = '' + end + + return prefix .. suffix +end + +local offline_ssid = calculate_offline_ssid() + +-- Count offline incidents +local tmp = '/tmp/ssid-changer-count' +local off_count = 0 +local file = io.open(tmp, 'r') + +if file then + off_count = tonumber(file:read("*a")) or 0 + file:close() +else + file = io.open(tmp, 'w') + file:write("0") + file:close() +end + +local function calculate_tq_limit() + local tq_limit_max = tonumber(uci:get('ssid-changer', 'settings', 'tq_limit_max') or 45) + local tq_limit_min = tonumber(uci:get('ssid-changer', 'settings', 'tq_limit_min') or 35) + local gateway_tq + + local handle = io.popen('batctl gwl -H | grep -e "^\\*" | awk -F"[()]" "{print $2}" | tr -d " "') + gateway_tq = tonumber(handle:read("*a")) + handle:close() + + if gateway_tq then + if gateway_tq >= tq_limit_max then + return 'online' + elseif gateway_tq < tq_limit_min then + return 'offline' + end + end + + return nil +end + +local function has_default_gw4() + local default_gw4 = io.open('/var/gluon/state/has_default_gw4', 'r') + if default_gw4 then + default_gw4:close() + return true + end + return false +end + +local status +if has_default_gw4() then + local tq_limit_enabled = tonumber(uci:get('ssid-changer', 'settings', 'tq_limit_enabled') or 0) + +if tq_limit_enabled == 1 then + status = calculate_tq_limit() +else + status = 'online' + end +else + status = 'offline' +end + +if status == 'online' then + log_debug("node is online") + os.execute('uci revert wireless && wifi reconf') +elseif status == 'offline' then + log_debug("node is considered offline") + local first = tonumber(uci:get('ssid-changer', 'settings', 'first') or 5) + -- set SSID offline, only if uptime is less than FIRST or exactly a multiplicative of switch_timeframe + if uptime_minutes < first or is_switch_time == 0 then + + -- check if off_count is more than half of the monitor duration + if off_count >= math.floor(monitor_duration / 2) then + -- if has been offline for at least half checks in monitor duration + -- set the SSID to the offline SSID + -- and disable owe client radios + for i = 0, 2 do + local client_ssid = uci:get('wireless', 'client_radio' .. i, 'ssid') + if client_ssid then + uci:set('wireless', 'client_radio' .. i, 'ssid', offline_ssid) + end + + local owe_ssid = uci:get('wireless', 'owe_radio' .. i, 'ssid') + if owe_ssid then + uci:set('wireless', 'owe_radio' .. i, 'enabled', 0) + end + uci:save('wireless') + end + os.execute('wifi reconf') + end + end + off_count = off_count + 1 + file = io.open(tmp, 'w') + file:write(tostring(off_count)) + file:close() +end + +if is_switch_time == 0 then + file = io.open(tmp, 'w') + file:write("0") + file:close() +end