gluon/package/gluon-offline-ssid/luasrc/usr/bin/gluon-offline-ssid.lua
rubo77 a6c48a1575
gluon-offline-ssid: restructure original gluon-ssid-changer code
- transcode ssid_changer.sh into Lua
- remove gluonShellDiet
- change default prefix to just "Offline_"
- extract gluon-web-offline-ssid
2020-02-02 17:30:47 +01:00

220 lines
7.5 KiB
Lua

#!/usr/bin/lua
local uci = require("simple-uci").cursor()
local util = require 'gluon.util'
local function safety_exit(t)
io.write(t .. ", exiting with error code 2")
os.exit(2)
end
local function logger(m)
os.execute('logger -s -t "gluon-offline-ssid" -p 5 "' .. m .. '"')
end
local function file_exists(name)
local f = io.open(name, "r")
return f ~= nil and io.close(f)
end
local ut = util.get_uptime()
if ut < 60 then
safety_exit('less than one minute')
end
-- only once every timeframe minutes the ssid will change to the offline-ssid
-- (set to 1 minute if you want to change immediately every time the router gets offline)
local minutes = tonumber(uci:get('gluon-offline-ssid', 'settings', 'switch_timeframe') or '30')
-- the first few minutes directly after reboot within which an offline-ssid always may be activated
-- (must be <= switch_timeframe)
local first = tonumber(uci:get('gluon-offline-ssid', 'settings', 'first') or '5')
-- the offline-ssid will start with this prefix use something short to leave space for the nodename
-- (no '~' allowed!)
local prefix = uci:get('gluon-offline-ssid', 'settings', 'prefix') or 'Offline_'
local disabled = uci:get('gluon-offline-ssid', 'settings', 'disabled') == '1' or false
if disabled then
print("offline-ssid is disabled")
end
local phys = { length = 0 }
uci:foreach('wireless', 'wifi-device', function(config)
local phy = util.find_phy(config)
if phy then
phys[config['.name']] = phy
phys['length'] = phys['length'] + 1
end
end)
if phys['length'] == 0 then
safety_exit('no hostapd-phys')
end
local ssids = { }
uci:foreach('wireless', 'wifi-iface', function(config)
if config['mode'] == 'ap' and config['network'] == 'client' then
local ssid = config['ssid']
if ssid then
table.insert(ssids, { ssid = ssid , phy = phys[config['device']] })
end
end
end)
if #ssids == 0 then
safety_exit('no ssids')
end
-- generate the ssid with either 'nodename', 'mac' or to use only the prefix set to 'none'
local settings_suffix = uci:get('gluon-offline-ssid', 'settings', 'suffix') or 'nodename'
local suffix
if settings_suffix == 'nodename' then
local pretty_hostname = require 'pretty_hostname'
suffix = pretty_hostname.get(uci)
-- 32 would be possible as well
if ( string.len(suffix) > 30 - string.len(prefix) ) then
-- calculate the length of the first part of the node identifier in the offline-ssid
local half = math.floor((28 - string.len(prefix) ) / 2)
-- jump to this charakter for the last part of the name
local skip = string.len(suffix) - half
-- use the first and last part of the nodename for nodes with long name
suffix = string.sub(suffix,0,half) .. '...' .. string.sub(suffix, skip)
end
elseif settings_suffix == 'mac' then
local sysconfig = require 'gluon.sysconfig'
suffix = sysconfig.primary_mac
else
-- 'none'
suffix = ''
end
local offline_ssid = prefix .. suffix
-- temp file to count the offline incidents during switch_timeframe
local tmp = '/tmp/offline-ssid-count'
local off_count = '0'
if not file_exists(tmp) then
assert(io.open(tmp, 'w')):write('0')
else
off_count = tonumber(util.readfile(tmp))
end
-- if tq_limit_enabled is true, the offline ssid will only be set if there is no gateway reacheable
-- upper and lower limit to turn the offline_ssid on and off
-- in-between these two values the ssid will never be changed to preven it from toggeling every minute.
local tq_limit_enabled = tonumber(uci:get('gluon-offline-ssid', 'settings', 'tq_limit_enabled') or '0')
local check
local msg
if ( tq_limit_enabled == 1 ) then
-- upper limit, above that the online ssid will be used
local tq_limit_max = tonumber(uci:get('gluon-offline-ssid', 'settings', 'tq_limit_max') or '45')
-- lower limit, below that the offline ssid will be used
local tq_limit_min = tonumber(uci:get('gluon-offline-ssid', 'settings', 'tq_limit_min') or '35')
-- grep the connection quality of the currently used gateway
local gateway_tq = util.exec('batctl gwl | grep -e "^=>" -e "^\\*" | awk -F \'[()]\' \'{print $2}\' | tr -d " "')
if ( gateway_tq == '' ) then
-- there is no gateway
gateway_tq = 0
end
msg = "tq is " .. gateway_tq
if ( gateway_tq >= tq_limit_max ) then
check = 1
elseif ( gateway_tq < tq_limit_min ) then
check = 0
else
-- get a clean run if we are in-between the grace period
print(msg .. ", do nothing")
os.exit(0)
end
else
msg = ""
check = os.execute('batctl gwl -H | grep -v "gateways in range"')
end
local up = ut / 60
local m = math.floor(up % minutes)
-- debug:
print("uptime in minutes:"..up..", every "..minutes.." minutes, countdown:"..m)
local hup_needed = 0
local ssid_grep = 'grep "^ssid='
-- debug:
-- check=0 -- set this to set the node always offline
if check > 0 or disabled then
print("node is online")
-- check status for all physical devices
for _, ssid in ipairs(ssids) do
local hostapd = '/var/run/hostapd-' .. ssid.phy .. '.conf'
-- first grep for online-SSID in hostapd file
if os.execute(ssid_grep .. ssid.ssid .. '" ' .. hostapd) == 0 then
print("current ssid is correct")
break
else
-- set online
-- debug: grep for offline_ssid in hostapd file
if os.execute(ssid_grep .. offline_ssid .. '" ' .. hostapd) ~= 0 then
logger('misconfiguration: did neither find ssid ' .. ssid.ssid .. ' nor ' .. offline_ssid .. '. please reboot')
end
local current_ssid = util.trim(util.exec(ssid_grep .. '" ' .. hostapd .. ' | cut -d"=" -f2'))
-- TODO: replace ~ in current_ssid and ssid.ssid
logger(msg .. ' - ssid is ' .. current_ssid .. ', change to ' .. ssid.ssid)
os.execute('sed -i "s~^ssid=' .. current_ssid .. '~ssid=' .. ssid.ssid .. '~" ' .. hostapd)
hup_needed = 1
end
end
elseif check == 0 then
print("node is considered offline")
if up < first or m == 0 then
-- set ssid offline, only if uptime is less than first or exactly a multiplicative of switch_timeframe
local t = minutes
if up < first then
t = first
end
if off_count >= t / 2 then
-- node was offline more times than half of switch_timeframe (or than first)
for _, ssid in ipairs(ssids) do
local hostapd = '/var/run/hostapd-' .. ssid.phy .. '.conf'
local current_ssid = util.trim(util.exec(ssid_grep .. '" ' .. hostapd .. ' | cut -d"=" -f2'))
-- first grep for offline_ssid in hostapd file
if os.execute(ssid_grep .. offline_ssid .. '" ' .. hostapd) == 0 then
print('ssid ' .. current_ssid .. ' is correct')
break
else
-- set offline
-- debug: grep for online-SSID in hostapd file
if os.execute(ssid_grep .. ssid.ssid .. '" ' .. hostapd) == 0 then
logger('misconfiguration: did neither find ssid '
.. ssid.ssid .. ' nor ' .. offline_ssid .. '. please reboot')
end
logger(msg .. ' - ' .. off_count .. ' times offline, ssid is '
.. current_ssid .. ', change to ' .. offline_ssid)
os.execute('sed -i "s~^ssid=' .. ssid.ssid .. '~ssid=' .. offline_ssid .. '~" ' .. hostapd)
hup_needed = 1
end
end
end
-- else print("minute ' .. m .. ', just count ' .. off_count .. '")
end
assert(io.open(tmp, 'w')):write(off_count + 1)
end
if hup_needed == 1 then
-- send hup to all hostapd to load the new ssid
os.execute('killall -hup hostapd')
print("hup!")
end
if m == 0 then
-- set counter to 0 if the timeframe is over
assert(io.open(tmp, 'w')):write('0')
end