Skip to content

Commit 19fc2d3

Browse files
authored
Merge pull request freifunk-gluon#138 from freifunk-gluon/improve_ssid_changer
ffac-ssid-changer: rewrite in lua, use wifi reconf
2 parents e81920e + b25e816 commit 19fc2d3

File tree

5 files changed

+228
-257
lines changed

5 files changed

+228
-257
lines changed

ffac-ssid-changer/Makefile

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,4 @@ define Package/$(PKG_NAME)/description
2424
most.
2525
endef
2626

27-
28-
define Build/Compile
29-
$(call Gluon/Build/Compile)
30-
./gluonShellDiet.sh shsrc/ssid-changer.sh > $(PKG_BUILD_DIR)/ssid-changer.sh
31-
endef
32-
33-
define Package/$(PKG_NAME)/install
34-
$(Gluon/Build/Install)
35-
36-
$(INSTALL_DIR) $(1)/lib/gluon/ssid-changer
37-
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ssid-changer.sh $(1)/lib/gluon/ssid-changer/
38-
endef
39-
40-
4127
$(eval $(call BuildPackageGluon,$(PKG_NAME)))
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* * * * * /lib/gluon/ssid-changer/ssid-changer.sh
1+
* * * * * /lib/gluon/ssid-changer/ssid-changer.lua

ffac-ssid-changer/gluonShellDiet.sh

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#!/usr/bin/lua
2+
3+
local uci = require('simple-uci').cursor()
4+
5+
-- Safety check functions
6+
local function log_debug(...)
7+
if uci:get('ssid-changer', 'settings', 'debug_log_enabled') == '1' then
8+
os.execute('logger -t "ffac-ssid-changer" -p debug "' .. table.concat({...}, ' ') .. '"')
9+
end
10+
end
11+
12+
local function log(...)
13+
os.execute('logger -t "ffac-ssid-changer" "' .. table.concat({...}, ' ') .. '"')
14+
end
15+
16+
local function safety_exit(message)
17+
log_debug(message .. ", exiting with error code 2")
18+
os.exit(2)
19+
end
20+
21+
-- Check if the script is enabled
22+
if uci:get('ssid-changer', 'settings', 'enabled') == '0' then
23+
os.exit(0) -- Exit silently if the script is disabled
24+
end
25+
26+
-- Check for autoupdater running
27+
local function is_autoupdater_running()
28+
local handle = io.popen('pgrep -f autoupdater')
29+
local result = handle:read("*a")
30+
handle:close()
31+
return result ~= ''
32+
end
33+
34+
if is_autoupdater_running() then
35+
safety_exit('autoupdater running')
36+
end
37+
38+
-- Read uptime
39+
local function get_uptime()
40+
local file = io.open('/proc/uptime', 'r')
41+
local uptime = file:read("*n") -- Read only the first number (uptime in seconds)
42+
file:close()
43+
return uptime
44+
end
45+
46+
local uptime = get_uptime()
47+
local uptime_minutes = math.floor(uptime / 60)
48+
local monitor_duration = tonumber(uci:get('ssid-changer', 'settings', 'switch_timeframe') or 30)
49+
local is_switch_time = uptime_minutes % monitor_duration
50+
51+
if uptime < 60 then
52+
safety_exit('uptime less than one minute')
53+
end
54+
55+
-- Check for hostapd processes
56+
local function has_hostapd_processes()
57+
local handle = io.popen('find /var/run -name "hostapd-*.conf" | wc -l')
58+
local result = handle:read("*a")
59+
handle:close()
60+
return tonumber(result) > 0
61+
end
62+
63+
if not has_hostapd_processes() then
64+
safety_exit('no hostapd-*')
65+
end
66+
67+
-- Generate the offline SSID
68+
local function calculate_offline_ssid()
69+
local prefix = uci:get('ssid-changer', 'settings', 'prefix') or 'FF_Offline_'
70+
local settings_suffix = uci:get('ssid-changer', 'settings', 'suffix') or 'nodename'
71+
local suffix
72+
73+
if settings_suffix == 'nodename' then
74+
suffix = io.popen('uname -n'):read("*a"):gsub("%s+", "")
75+
if #suffix > (30 - #prefix) then
76+
local max_suffix_length = math.floor((28 - #prefix) / 2)
77+
local suffix_first_chars = suffix:sub(1, max_suffix_length)
78+
local suffix_last_chars = suffix:sub(-max_suffix_length)
79+
suffix = suffix_first_chars .. '...' .. suffix_last_chars
80+
end
81+
elseif settings_suffix == 'mac' then
82+
suffix = io.popen('uci -q get network.bat0.macaddr | sed "s/://g"'):read("*a"):gsub("%s+", "")
83+
else
84+
suffix = ''
85+
end
86+
87+
return prefix .. suffix
88+
end
89+
90+
local offline_ssid = calculate_offline_ssid()
91+
92+
-- Count offline incidents
93+
local tmp = '/tmp/ssid-changer-count'
94+
local tmp_state = '/tmp/ssid-changer-offline'
95+
local off_count = 0
96+
local file = io.open(tmp, 'r')
97+
98+
local is_offline = 0
99+
local state_file = io.open(tmp_state, 'r')
100+
101+
if state_file then
102+
is_offline = tonumber(state_file:read("*a")) or 0
103+
state_file:close()
104+
else
105+
state_file = io.open(tmp_state, 'w')
106+
state_file:write("0")
107+
state_file:close()
108+
end
109+
110+
if file then
111+
off_count = tonumber(file:read("*a")) or 0
112+
file:close()
113+
else
114+
file = io.open(tmp, 'w')
115+
file:write("0")
116+
file:close()
117+
end
118+
119+
local function calculate_tq_limit()
120+
local tq_limit_max = tonumber(uci:get('ssid-changer', 'settings', 'tq_limit_max') or 45)
121+
local tq_limit_min = tonumber(uci:get('ssid-changer', 'settings', 'tq_limit_min') or 35)
122+
local gateway_tq
123+
124+
local handle = io.popen('batctl gwl -H | grep -e "^\\*" | awk -F"[()]" "{print $2}" | tr -d " "')
125+
gateway_tq = tonumber(handle:read("*a"))
126+
handle:close()
127+
128+
if not gateway_tq then
129+
safety_exit('tq_limit can not be calculated without gateway')
130+
end
131+
local is_online
132+
133+
if gateway_tq >= tq_limit_max then
134+
is_online = true
135+
elseif gateway_tq < tq_limit_min then
136+
is_online = false
137+
else
138+
-- in the middle part we consider us offline if there was at least one offline incidents
139+
-- or we were offline before the current monitor interval
140+
is_online = off_count > 0
141+
end
142+
143+
if is_online then
144+
return 'online'
145+
else
146+
return 'offline'
147+
end
148+
end
149+
150+
local function has_default_gw4()
151+
local default_gw4 = io.open('/var/gluon/state/has_default_gw4', 'r')
152+
if default_gw4 then
153+
default_gw4:close()
154+
return true
155+
end
156+
return false
157+
end
158+
159+
local status
160+
if has_default_gw4() then
161+
local tq_limit_enabled = tonumber(uci:get('ssid-changer', 'settings', 'tq_limit_enabled') or 0)
162+
163+
if tq_limit_enabled == 1 then
164+
status = calculate_tq_limit()
165+
else
166+
status = 'online'
167+
end
168+
else
169+
status = 'offline'
170+
end
171+
172+
if status == 'online' then
173+
log_debug("node is online")
174+
-- only revert and reconf if we were offline in the current monitoring timeframe or before
175+
-- to reduce impact
176+
if off_count > 0 then
177+
log("reverting offline ssid back to default wireless config")
178+
uci:revert('wireless')
179+
os.execute('wifi reconf')
180+
end
181+
elseif status == 'offline' then
182+
log_debug("node is considered offline")
183+
local first = tonumber(uci:get('ssid-changer', 'settings', 'first') or 5)
184+
-- set SSID offline, only if uptime is less than FIRST or exactly a multiplicative of switch_timeframe
185+
if uptime_minutes < first or is_switch_time == 0 then
186+
187+
-- check if off_count is more than half of the monitor duration
188+
if not is_offline and off_count >= math.floor(monitor_duration / 2) then
189+
-- if has been offline for at least half checks in monitor duration
190+
-- set the SSID to the offline SSID
191+
-- and disable owe client radios
192+
for i = 0, 2 do
193+
local client_ssid = uci:get('wireless', 'client_radio' .. i, 'ssid')
194+
if client_ssid then
195+
uci:set('wireless', 'client_radio' .. i, 'ssid', offline_ssid)
196+
end
197+
198+
local owe_ssid = uci:get('wireless', 'owe_radio' .. i, 'ssid')
199+
if owe_ssid then
200+
uci:set('wireless', 'owe_radio' .. i, 'disabled', 1)
201+
end
202+
-- save does not commit
203+
uci:save('wireless')
204+
end
205+
log("reconfiguring wifi to offline ssid")
206+
os.execute('wifi reconf')
207+
end
208+
end
209+
off_count = off_count + 1
210+
file = io.open(tmp, 'w')
211+
file:write(tostring(off_count))
212+
file:close()
213+
end
214+
215+
if is_switch_time == 0 then
216+
file = io.open(tmp, 'w')
217+
state_file = io.open(tmp_state, 'w')
218+
219+
if status == 'offline' then
220+
file:write("1")
221+
state_file:write("1")
222+
else
223+
file:write("0")
224+
state_file:write("0")
225+
end
226+
file:close()
227+
end

0 commit comments

Comments
 (0)