#!/usr/bin/lua
--[[
Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks
Copyright (C) 2021 Tim Wilkinson
Original Perl Copyright (C) 2015 Conrad Lara
See Contributors file for additional contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Additional Terms:
Additional use restrictions exist on the AREDN(TM) trademark and logo.
See AREDNLicense.txt for more info.
Attributions to the AREDN Project must be retained in the source code.
If importing this code into a new or existing project attribution
to the AREDN project must be added to the source code.
You must not misrepresent the origin of the material contained within.
Modified versions must be modified to attribute to the original source
and be marked in reasonable ways as differentiate it from the original
version
--]]
require("nixio")
require("aredn.hardware")
require("aredn.http")
require("aredn.utils")
require("aredn.olsr")
local html = require("aredn.html")
require("uci")
require("aredn.info")
-- helpers start
function mesh_ip_to_hostnames(ip)
if not ip or ip == "" or ip == "none" then
return ""
end
local pattern = "^" .. ip .. "%s+([%w%-%.]+)"
local host = "none"
for line in io.lines("/etc/hosts")
do
local host = line:match(pattern)
if host then
return host.gsub("%s+", " / ")
end
end
for line in aredn.olsr.getHostAsLines()
do
local host = line:match(pattern)
if host then
host = host:gsub("^dtdlink%.","")
host = host:gsub("^mid[0-9]*%.","")
host = host:gsub("%.local.mesh$","")
return host
end
end
return host
end
function get_default_gw(iface)
-- wan will route via table 254 default gw
-- wifi will route via OLSR table 31 default gw
local rtable = ""
if iface == "wan" then
rtable = "ip route list table 254"
elseif iface == "wifi" then
rtable = "ip route list table 31"
else
return "none"
end
local p = io.popen(rtable)
if p then
for line in p:lines()
do
local gw = line:match("^default%svia%s([%d%.]+)")
if gw then
p:close()
return gw
end
end
p:close()
end
return "none"
end
function get_memavail()
local f = io.open("/proc/meminfo", "r")
if f then
for line in f:lines()
do
local memavail = line:match("^MemAvailable:%s+(%d+)%s+kB")
if memavail then
f:close()
return tonumber(memavail)
end
end
f:close()
end
return 0
end
function get_wifi_signal(wifiif)
local signal = -1000
local noise = -1000
for mac, station in pairs(iwinfo.nl80211.assoclist(wifiif))
do
if station.signal ~= 0 and station.signal > signal then
signal = station.signal
end
if station.noise ~= 0 and station.noise > noise then
noise = station.noise
end
end
if signal == -1000 or noise == -1000 then
return "none", "none"
else
if signal > 0 then
signal = (0 - signal)
end
if noise > 0 then
noise = (0 - noise)
end
return signal, noise
end
end
-- helpers end
local node = aredn.info.get_nvram("node")
if node == "" then
node = "NOCALL"
end
local tactical = aredn.info.get_nvram("tactical")
local config = aredn.info.get_nvram("config")
if config == "" or nixio.fs.stat("/etc/config.mesh", "type") ~= "dir" then
config = "not set"
end
local haswifi = aredn.hardware.has_wifi()
local wifi_iface = aredn.hardware.get_iface_name("wifi")
local wifi_nr = wifi_iface:match("wlan(%d+)")
local wifi_disabled = true
local radio = "radio0"
if haswifi and wifi_nr then
wifi_disabled = false
radio = "radio" .. wifi_nr
end
local cursor = uci.cursor()
local wifi_channel
local wifi_chanbw
local wifi_freq_range = ""
local wifi_ssid
if not wifi_disabled then
wifi_channel = cursor:get("wireless", radio, "channel")
wifi_channel = tonumber(wifi_channel) or 0
wifi_chanbw = tonumber(cursor:get("wireless", radio, "chanbw") or "20")
local rfchans = aredn.hardware.get_rfchannels(wifi_iface)
if rfchans and rfchans[1] then
local basefreq = rfchans[1].frequency
if basefreq > 3000 and basefreq < 5000 then
wifi_channel = wifi_channel * 5 + 3000
elseif basefreq > 900 and basefreq < 2300 then
wifi_channel = wifi_channel * 5 + 887
end
for _, chan in ipairs(rfchans)
do
if chan.number == wifi_channel then
wifi_freq_range = (chan.frequency - wifi_chanbw / 2) .. " - " .. (chan.frequency + wifi_chanbw / 2) .. " MHz"
break
end
end
end
wifi_ssid = "none"
cursor:foreach("wireless", "wifi-iface",
function (section)
if section.network == "wifi" then
wifi_ssid = section.ssid
return false
end
end
)
end
local node_desc = cursor:get("system", "@system[0]", "description")
local lat_lon = "Location Not Available"
local lat = cursor:get("aredn", "@location[0]", "lat")
local lon = cursor:get("aredn", "@location[0]", "lon")
if lat and lon then
lat_lon = string.format("
Location: %s %s
", lat, lon)
end
local host_total = 0
local host_nodes = 0
for line in aredn.olsr.getHostAsLines()
do
if line:match("^10%.") and not line:match("%smid%d+%.") then
host_total = host_total + 1
local host = line:match("^10%..+%sdtdlink%.")
if host then
host_nodes = host_nodes + 1
end
end
end
-- post data
if os.getenv("REQUEST_METHOD") == "POST" then
require('luci.http')
local request = luci.http.Request(nixio.getenv(),
function()
local v = io.read(1024)
if not v then
io.close()
end
return v
end
)
local css = request:formvalue("css")
if css and css:match("%.css$") and nixio.fs.stat("/www/" .. css) then
nixio.fs.unlink("/tmp/web/style.css")
nixio.fs.symlink("/www/" .. css, "/tmp/web/style.css")
end
end
-- generate page
http_header()
html.header(node .. " status", true)
html.print("")
html.footer()
html.print("