-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
04813d8
commit 0ef983d
Showing
3 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
include $(TOPDIR)/rules.mk | ||
|
||
PKG_NAME:=ffh-obedient-meshing | ||
PKG_VERSION:=1 | ||
PKG_RELEASE:=1 | ||
|
||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||
|
||
include $(TOPDIR)/../package/gluon.mk | ||
|
||
define Package/ffh-obedient-meshing | ||
SECTION:=ffh | ||
CATEGORY:=FFH | ||
TITLE:=Automatically switch to the most popular domain in wifi reach, as soon as no mesh neighbours are available. | ||
DEPENDS:=+gluon-core +gluon-state-check +iw +libiwinfo-lua +micrond @GLUON_MULTIDOMAIN | ||
MAINTAINER:=Freifunk Hannover <[email protected]> | ||
endef | ||
|
||
define Package/ffh-obedient-meshing/description | ||
This package checks periodically, whether the router has mesh-neighbours. | ||
If it doesn't, | ||
it scans for mesh-networks, | ||
filters out the ones that are not part of its site and domainconf, | ||
joins the most popular across all radios, regardless of their band. | ||
It does so by switching its own domain. | ||
endef | ||
|
||
$(eval $(call BuildPackageGluon,$(PKG_NAME))) |
1 change: 1 addition & 0 deletions
1
ffh-obedient-meshing/files/usr/lib/micron.d/ffh-obedient-meshing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* * * * * sleep 10 && /usr/sbin/ffh-obedient-meshing |
152 changes: 152 additions & 0 deletions
152
ffh-obedient-meshing/luasrc/usr/sbin/ffh-obedient-meshing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
#!/usr/bin/lua | ||
local uci = require("simple-uci").cursor() | ||
local iwinfo = require "iwinfo" | ||
local util = require "gluon.util" | ||
local json = require "jsonc" | ||
local sys_stat = require "posix.sys.stat" | ||
local isreg = require "posix.sys.stat".S_ISREG | ||
local isdir = require "posix.sys.stat".S_ISDIR | ||
local unistd = require "posix.unistd" | ||
|
||
|
||
local function has_state() | ||
local state_path="/var/gluon/state" | ||
local stat=sys_stat.lstat(state_path) | ||
if nil~=stat then | ||
return 0~=isdir(stat.st_mode) | ||
end | ||
return false | ||
end | ||
|
||
local function has_neighbours() | ||
local neighbours_path="/var/gluon/state/has_neighbours" | ||
local stat=sys_stat.stat(neighbours_path) | ||
if nil~=stat then | ||
return 0~=isreg(stat.st_mode) | ||
end | ||
return false | ||
end | ||
|
||
local function get_band(channel) | ||
if channel >= 1 and channel <=14 then | ||
return "wifi24" | ||
elseif channel >= 36 and channel <= 165 then | ||
return "wifi5" | ||
end | ||
end | ||
|
||
local function get_available_wifi_networks() | ||
local radios = {} | ||
local ssid_counts = {} | ||
ssid_counts["wifi24"]={} | ||
ssid_counts["wifi5"]={} | ||
|
||
uci:foreach('wireless', 'wifi-device', | ||
function(s) | ||
radios[s['.name']] = {} | ||
end | ||
) | ||
|
||
for radio, _ in pairs(radios) do | ||
local wifitype = iwinfo.type(radio) | ||
local iw = iwinfo[wifitype] | ||
if not iw then | ||
return nil | ||
end | ||
local tmplist = iw.scanlist(radio) | ||
for _, net in ipairs(tmplist) do | ||
if net.mode and net.channel and net.ssid and "Mesh Point"==net.mode then | ||
local band = get_band(net.channel) | ||
if nil==ssid_counts[band][net.ssid] then | ||
ssid_counts[band][net.ssid]=1 | ||
else | ||
ssid_counts[band][net.ssid]=ssid_counts[band][net.ssid]+1 | ||
end | ||
end | ||
end | ||
end | ||
return ssid_counts | ||
end | ||
|
||
|
||
local function get_domain_list() | ||
local list = {} | ||
for _, domain_path in ipairs(util.glob('/lib/gluon/domains/*.json')) do | ||
local is_primary = 0~=isreg(sys_stat.lstat(domain_path).st_mode) | ||
if is_primary then | ||
local domain_code = domain_path:match('([^/]+)%.json$') | ||
local domain = assert(json.load(domain_path)) | ||
|
||
table.insert(list, { | ||
domain_code = domain_code, | ||
domain_name = domain.domain_names[domain_code], | ||
wifi24 = domain.wifi24.mesh.id, | ||
wifi5 = domain.wifi5.mesh.id | ||
}) | ||
end | ||
end | ||
|
||
table.sort(list, function(a, b) return a.domain_name < b.domain_name end) | ||
return list | ||
end | ||
|
||
|
||
local function to_domain_counts(band_ssid_counts) | ||
local domain_code_counts={} | ||
local domain_list = get_domain_list() | ||
local function get_domaincode(band, ssid) | ||
for _, domain in pairs(domain_list) do | ||
if domain[band]==ssid then | ||
return domain["domain_code"] | ||
end | ||
end | ||
end | ||
|
||
for band, countlist in pairs(band_ssid_counts) do | ||
--print(band) | ||
for ssid, count in pairs(countlist) do | ||
--print(ssid .. ": " ..count) | ||
local code = get_domaincode(band, ssid) | ||
if nil~=code then | ||
--print(code .. ": +" ..count) | ||
if nil==domain_code_counts[code] then | ||
domain_code_counts[code]=count | ||
else | ||
domain_code_counts[code]=domain_code_counts[code]+count | ||
end | ||
end | ||
end | ||
end | ||
|
||
return domain_code_counts | ||
end | ||
|
||
if not has_state() then | ||
print("Device state is not available yet, aborting.") | ||
os.exit() | ||
end | ||
|
||
if has_neighbours() then | ||
print("Device still has neighbours, no need to rescan.") | ||
os.exit() | ||
end | ||
|
||
local selected_domain = uci:get('gluon', 'core', 'domain') | ||
print("selected domain: " .. selected_domain) | ||
local networks = get_available_wifi_networks() | ||
|
||
local dom_counts = to_domain_counts(networks) | ||
|
||
local high = 0 | ||
local high_dom | ||
for dom, count in pairs(dom_counts) do | ||
if count >= high then | ||
high=count | ||
high_dom=dom | ||
end | ||
end | ||
print(high_dom .. ": " .. high) | ||
|
||
|
||
local cmd = {[0]="gluon-switch-domain", "--no-reboot", high_dom} | ||
unistd.execp(cmd[0], cmd) |