initial commit

This commit is contained in:
Travis Herbranson 2026-06-30 05:49:51 -04:00
commit 7432d7ab83
10 changed files with 287 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# Python-generated files
__pycache__/
*.py[oc]
build/
dist/
wheels/
*.egg-info
# Virtual environments
.venv

1
.python-version Normal file
View File

@ -0,0 +1 @@
3.12

0
README.md Normal file
View File

6
main.py Normal file
View File

@ -0,0 +1,6 @@
def main():
print("Hello from pi-modem!")
if __name__ == "__main__":
main()

7
pyproject.toml Normal file
View File

@ -0,0 +1,7 @@
[project]
name = "pi-modem"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []

8
uv.lock generated Normal file
View File

@ -0,0 +1,8 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "pi-modem"
version = "0.1.0"
source = { virtual = "." }

91
wifi-dns Executable file
View File

@ -0,0 +1,91 @@
#!/usr/bin/lua
local json = require("luci.jsonc")
local function sh(cmd)
local h = io.popen(cmd .. " 2>&1")
local out = h:read("*a")
local ok = h:close()
return ok, out
end
local function get_servers()
local h = io.popen("uci -q get dhcp.@dnsmasq[0].server 2>/dev/null")
local out = h:read("*a") or ""
h:close()
local list = {}
for s in out:gmatch("%S+") do list[#list+1] = s end
return list
end
local function get_noresolv()
local h = io.popen("uci -q get dhcp.@dnsmasq[0].noresolv 2>/dev/null")
local out = (h:read("*a") or ""):gsub("%s+", "")
h:close()
return out == "1"
end
local function read_state()
return {
noresolv = get_noresolv(),
servers = get_servers(),
}
end
io.write("Content-Type: application/json\r\n\r\n")
local body = io.read("*a") or ""
local req = json.parse(body) or {}
local action = req.action or "status"
local ADGUARD = "127.0.0.1#5335"
if action == "status" then
io.write(json.stringify({ ok = true, state = read_state() }))
os.exit(0)
end
local function set_noresolv(v)
sh("uci set dhcp.@dnsmasq[0].noresolv='" .. (v and "1" or "0") .. "'")
end
local function clear_servers()
sh("uci -q delete dhcp.@dnsmasq[0].server")
end
local function add_server(s)
sh("uci add_list dhcp.@dnsmasq[0].server='" .. s .. "'")
end
local function apply()
sh("uci commit dhcp")
sh("/etc/init.d/dnsmasq restart")
end
if action == "normal" then
clear_servers()
add_server(ADGUARD)
set_noresolv(true)
apply()
elseif action == "portal" then
clear_servers()
set_noresolv(false)
apply()
elseif action == "set" then
if req.noresolv ~= nil then set_noresolv(req.noresolv and true or false) end
if req.servers ~= nil then
clear_servers()
for _, s in ipairs(req.servers) do
if s and s ~= "" then add_server(s) end
end
end
apply()
else
io.write(json.stringify({ ok = false, error = "unknown action: " .. tostring(action) }))
os.exit(0)
end
io.write(json.stringify({ ok = true, action = action, state = read_state() }))

73
wifi-join Executable file
View File

@ -0,0 +1,73 @@
#!/usr/bin/lua
local json = require("luci.jsonc")
local function uci(cmd)
local h = io.popen("uci " .. cmd .. " 2>&1")
local out = h:read("*a")
local ok = h:close()
return ok, out
end
local function next_uplink_index()
local h = io.popen("uci show wireless 2>/dev/null | grep -o 'trm_uplink[0-9]*' | grep -o '[0-9]*'")
local used = {}
for n in h:lines() do used[tonumber(n)] = true end
h:close()
local i = 0
while used[i] do i = i + 1 end
return i
end
io.write("Content-Type: application/json\r\n\r\n")
local body = io.read("*a") or ""
local req = json.parse(body)
if not req or not req.ssid or req.ssid == "" then
io.write(json.stringify({ ok = false, error = "missing ssid" }))
os.exit(0)
end
local ssid = req.ssid
local key = req.key
local secured = req.secured and true or false
if secured and (not key or key == "") then
io.write(json.stringify({ ok = false, error = "secured network requires key" }))
os.exit(0)
end
local idx = next_uplink_index()
local sec = "wireless.trm_uplink" .. idx
local function q(s) return "'" .. tostring(s):gsub("'", "'\\''") .. "'" end
uci("set " .. sec .. "=wifi-iface")
uci("set " .. sec .. ".device='radio0'")
uci("set " .. sec .. ".mode='sta'")
uci("set " .. sec .. ".network='tm_wwan'")
uci("set " .. sec .. ".ssid=" .. q(ssid))
uci("set " .. sec .. ".disabled='0'")
if secured then
uci("set " .. sec .. ".encryption='psk2+ccmp'")
uci("set " .. sec .. ".key=" .. q(key))
else
uci("set " .. sec .. ".encryption='none'")
end
local up = "travelmate.trm_uplink" .. idx
uci("set " .. up .. "=uplink")
uci("set " .. up .. ".device='radio0'")
uci("set " .. up .. ".ssid=" .. q(ssid))
uci("set " .. up .. ".enabled='1'")
local ok_w = uci("commit wireless")
local ok_t = uci("commit travelmate")
io.write(json.stringify({
ok = (ok_w and ok_t) and true or false,
ssid = ssid,
section = "trm_uplink" .. idx,
secured = secured,
}))

53
wifi-scan Executable file
View File

@ -0,0 +1,53 @@
#!/usr/bin/lua
local function read_scan()
local h = io.popen("ubus call iwinfo scan '{\"device\":\"radio0\"}' 2>/dev/null")
local raw = h:read("*a")
h:close()
return raw
end
local function jsondec(s)
local json = require("luci.jsonc")
return json.parse(s)
end
local function jsonenc(t)
local json = require("luci.jsonc")
return json.stringify(t)
end
io.write("Content-Type: application/json\r\n\r\n")
local raw = read_scan()
local data = raw and jsondec(raw)
if not data or not data.results then
io.write(jsonenc({ ok = false, error = "scan failed or no results" }))
os.exit(0)
end
local best = {}
for _, n in ipairs(data.results) do
local ssid = n.ssid
if ssid and ssid ~= "" then
local prev = best[ssid]
if not prev or (n.signal or -999) > prev.signal then
best[ssid] = {
ssid = ssid,
signal = n.signal or -999,
quality = n.quality or 0,
quality_max = n.quality_max or 70,
band = n.band,
channel = n.channel,
secured = n.encryption and n.encryption.enabled or false,
}
end
end
end
local list = {}
for _, v in pairs(best) do list[#list+1] = v end
table.sort(list, function(a, b) return a.signal > b.signal end)
io.write(jsonenc({ ok = true, networks = list }))

38
wifi-status Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/lua
local json = require("luci.jsonc")
io.write("Content-Type: application/json\r\n\r\n")
local f = io.open("/tmp/trm_runtime.json", "r")
if not f then
io.write(json.stringify({ ok = false, error = "no runtime file" }))
os.exit(0)
end
local raw = f:read("*a")
f:close()
local rt = json.parse(raw)
if not rt or not rt.data then
io.write(json.stringify({ ok = false, error = "bad runtime json" }))
os.exit(0)
end
local d = rt.data
local status = d.travelmate_status or ""
local connected = status:match("^connected") ~= nil
local net_ok = status:match("net ok") ~= nil
local ssid = nil
if d.station_id then
ssid = d.station_id:match("radio0/(.+)/%-") or d.station_id:match("radio0/(.+)/")
end
io.write(json.stringify({
ok = true,
connected = connected,
net_ok = net_ok,
ssid = ssid,
raw_status = status,
}))