Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • autinerd/experimental-openwrt-24.10
  • experimental
  • feature/addMikrotikwAP
  • master
  • nrb/airmax-test
  • nrb/ar9344-reset-sequence
  • nrb/ex400-remove-wps
  • nrb/gluon-master-cpe510
  • nrb/test-radv-filter
  • nrbffs/fastd-remove-delay
  • nrbffs/netgear-ex6120
  • v2018.2.2-ffs
  • v2018.2.3-ffs
  • v2019.1-ffs
  • v2019.1.1-ffs
  • v2019.1.2-ffs
  • v2020.1-ffs
  • v2020.1.1-ffs
  • v2020.1.3-ffs
  • v2020.2-ffs
  • v2020.2.1-ffs
  • v2020.2.2-ffs
  • v2020.2.3-ffs
  • v2021.1-ffs
  • v2021.1.1-ffs
  • v2021.1.2-ffs
  • v2022.1.1-ffs
  • v2022.1.3-ffs
  • v2022.1.4-ffs
  • v2023.1-ffs
  • v2023.2-ffs
  • v2023.2.2-ffs
  • v2023.2.3-ffs
  • v2023.2.4-ffs
  • v2023.2.5-ffs
  • experimental-2022-09-24
  • experimental-2022-09-24-base
  • experimental-2023-03-11
  • experimental-2023-03-11-base
  • experimental-2023-03-12
  • experimental-2023-03-12-base
  • experimental-2023-03-16
  • experimental-2023-03-16-base
  • experimental-2023-03-20
  • experimental-2023-03-20-base
  • experimental-2023-03-23
  • experimental-2023-03-23-base
  • experimental-2023-03-25
  • experimental-2023-03-25-base
  • experimental-2023-03-26
  • experimental-2023-03-26-base
  • experimental-2023-03-30
  • experimental-2023-03-30-base
  • experimental-2023-03-31
  • experimental-2023-03-31-base
  • experimental-2023-04-01
  • experimental-2023-04-01-base
  • experimental-2023-04-08
  • experimental-2023-04-08-base
  • experimental-2023-04-10
  • experimental-2023-04-10-base
  • experimental-2023-04-13
  • experimental-2023-04-13-base
  • experimental-2023-04-15
  • experimental-2023-04-15-base
  • experimental-2023-04-16
  • experimental-2023-04-16-base
  • experimental-2023-04-18
  • experimental-2023-04-18-base
  • experimental-2023-04-20
  • experimental-2023-04-20-base
  • experimental-2023-04-26
  • experimental-2023-04-26-base
  • experimental-2023-04-28
  • experimental-2023-04-28-base
  • experimental-2023-04-30
  • experimental-2023-04-30-base
  • experimental-2023-05-02
  • experimental-2023-05-02-base
  • experimental-2023-05-03
  • experimental-2023-05-03-base
  • experimental-2023-05-12
  • experimental-2023-05-12-base
  • experimental-2023-05-21
  • experimental-2023-05-21-base
  • experimental-2023-05-25
  • experimental-2023-05-25-base
  • experimental-2023-07-02
  • experimental-2023-07-02-base
  • experimental-2023-07-04
  • experimental-2023-07-04-base
  • experimental-2023-07-12
  • experimental-2023-07-12-base
  • experimental-2023-07-16
  • experimental-2023-07-16-base
  • experimental-2023-08-04
  • experimental-2023-08-04-base
  • experimental-2023-08-10
  • experimental-2023-08-10-base
  • experimental-2023-09-08
  • experimental-2023-09-08-base
  • experimental-2023-09-09
  • experimental-2023-09-09-base
  • experimental-2023-09-10
  • experimental-2023-09-10-base
  • experimental-2023-09-11
  • experimental-2023-09-11-base
  • experimental-2023-09-12
  • experimental-2023-09-12-base
  • experimental-2023-09-13
  • experimental-2023-09-13-base
  • experimental-2023-09-15
  • experimental-2023-09-15-base
  • experimental-2023-09-16
  • experimental-2023-09-16-base
  • experimental-2023-09-18
  • experimental-2023-09-18-base
  • experimental-2023-09-20
  • experimental-2023-09-20-base
  • experimental-2023-09-27
  • experimental-2023-09-27-base
  • experimental-2023-09-28
  • experimental-2023-09-28-base
  • experimental-2023-09-29
  • experimental-2023-09-29-base
  • experimental-2023-10-02
  • experimental-2023-10-02-base
  • experimental-2023-10-13
  • experimental-2023-10-13-base
  • experimental-2023-10-14
  • experimental-2023-10-14-base
  • experimental-2023-10-16
  • experimental-2023-10-16-base
  • experimental-2023-10-23
  • experimental-2023-10-23-base
137 results

Target

Select target project
  • firmware/gluon
  • 0x4A6F/gluon
  • patrick/gluon
3 results
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • 2014.3.x
  • 2014.4.x
  • babel
  • experimental
  • hoodselector
  • master
  • nrb/gluon-master-cpe510
  • nrb/test-radv-filter
  • nrbffs/fastd-remove-delay
  • nrbffs/netgear-ex6120
  • radv-filterd
  • v2015.1.x
  • v2016.1.x
  • v2016.2.4-batmanbug
  • v2016.2.x
  • v2018.2.2-ffs
  • v2018.2.3-ffs
  • v2018.2.x
  • v2019.1-ffs
  • v2019.1.1-ffs
  • v2019.1.2-ffs
  • v2020.1-ffs
  • v2020.1.1-ffs
  • v2020.1.3-ffs
  • v2020.2-ffs
  • v2020.2.1-ffs
  • v2020.2.2-ffs
  • v2020.2.3-ffs
  • v2020.2.x
  • v2021.1-ffs
  • v2021.1.1-ffs
  • v2021.1.2-ffs
  • v2014.1
  • v2014.2
  • v2014.3
  • v2014.3.1
  • v2014.4
  • v2015.1
  • v2015.1.1
  • v2015.1.2
  • v2016.1
  • v2016.1.1
  • v2016.1.2
  • v2016.1.3
  • v2016.1.4
  • v2016.1.5
  • v2016.1.6
  • v2016.2
  • v2016.2.1
  • v2016.2.2
  • v2016.2.3
  • v2016.2.4
  • v2016.2.5
  • v2016.2.6
  • v2016.2.7
  • v2017.1
  • v2017.1.1
  • v2017.1.2
  • v2017.1.3
  • v2017.1.4
  • v2017.1.5
  • v2017.1.6
  • v2017.1.7
  • v2017.1.8
  • v2018.1
  • v2018.1.1
  • v2018.1.2
  • v2018.1.3
  • v2018.1.4
  • v2018.2
  • v2018.2-ffs0.1
  • v2018.2.1
  • v2018.2.1-ffs0.1
  • v2018.2.2-ffs0.1
  • v2018.2.3-ffs0.1
  • v2019.1-ffs0.1
  • v2019.1.1-ffs0.1
  • v2019.1.2-ffs0.1
  • v2020.1-ffs0.1
  • v2020.1.1-ffs0.1
  • v2020.1.3-ffs0.1
  • v2020.2
  • v2020.2-ffs0.1
  • v2020.2.1-ffs0.1
  • v2020.2.2-ffs0.1
  • v2020.2.3-ffs0.1
  • v2020.2.3-ffs0.2
  • v2020.2.3-ffs0.3
  • v2020.2.x-ffs0.1
  • v2021.1-ffs0.1
  • v2021.1.1-ffs0.1
  • v2021.1.1-ffs0.2
  • v2021.1.1-ffs0.3
  • v2021.1.1-ffs0.4
  • v2021.1.2-ffs0.1
  • v2021.1.2-ffs0.2
98 results
Show changes
Showing
with 444 additions and 147 deletions
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-state-check
include ../gluon.mk
define Package/gluon-state-check
TITLE:=Provides info about the routers state
DEPENDS:=+gluon-core +micrond
endef
define Package/gluon-state-check/description
gluon-state-check executes checks in `/lib/gluon/state/check.d/` and provides
a flag file for each check in `/var/gluon/state` depending on the return code
of the check. A flag file is created (or "touched") if the corresponding check
exits cleanly and gets removed otherwise. If the flags are "touched", they
are only accessed, but not modified. In this way, the atime of a flag file
reflects when the last check was performed and the mtime reflects when
when the state was last changed.
This package provides the following checks:
- `has_default_gw6` - check whether the router has a default IPv6-route on br-client.
- `has_ntp_sync` - check whether the last stratum event of busybox ntpd was <16
- `has_lost_ntp_sync` - check whether the last stratum event of busybox was 16
The checks are executed once every minute (by micron.d).
The two NTP checks are hotplug results of ntpd and as a result not available
in the first 11 minutes of uptime.
endef
$(eval $(call BuildPackageGluon,gluon-state-check))
#!/bin/sh
sync_flag="/var/gluon/state/has_ntp_sync"
unsync_flag="/var/gluon/state/has_lost_ntp_sync"
# shellcheck disable=SC2154 # stratum is set by busybox ntpd.
if [ "$stratum" = 16 ]
then
touch -a "$unsync_flag"
rm -f "$sync_flag"
elif [ "$stratum" -lt 16 ]
then
touch -a "$sync_flag"
rm -f "$unsync_flag"
fi
#!/bin/sh
out=$(ip -6 route show default dev br-client 2>/dev/null) && [ -n "$out" ]
#!/bin/busybox sh
# Show the current ntp state using gluon-state-check.
#
# In case of an unsynced ntp session the file has_lost_ntp_sync is created.
# Its atime will be bumped upon further failed synchronizations.
# As long as there is no sync, the file has_ntp_sync is absent.
#
# Vice versa, the file has_ntp_sync is created upon stratum-level <16.
# As long as the sync persists, only the files atime is updated.
# Furthermore, if there is an ntp sync, the file has_lost_ntp_sync is deleted.
#
# This allows the following code to emit the current ntp status and how long its been going on.
# These two variables must not contain spaces in order for the awk splitting to work.
HAS_LOST_NTP_SYNC="/var/gluon/state/has_lost_ntp_sync"
HAS_NTP_SYNC="/var/gluon/state/has_ntp_sync"
get_duration() {
local flag_file
local use_atime
local mtime
local time_epoch
local current_time
flag_file=$1
use_atime=$2
if [ "$use_atime" = true ]; then
ls_option="-u"
fi
# shellcheck disable=SC2012 # stat is unavailable and busybox find does not emit the necessary fields.
mtime=$(ls -l "$ls_option" "$flag_file" --full-time | awk '{print $6, $7}') 2>/dev/null
time_epoch=$(date -d "$mtime" +%s)
current_time=$(date +%s)
echo $((current_time - time_epoch))
}
if [ -f "$HAS_NTP_SYNC" ]; then
duration=$(get_duration "$HAS_NTP_SYNC")
last_checked=$(get_duration "$HAS_NTP_SYNC" true)
echo "NTP has been synced for $duration seconds (last checked $last_checked seconds ago)."
elif [ -f "$HAS_LOST_NTP_SYNC" ]; then
duration=$(get_duration "$HAS_LOST_NTP_SYNC")
last_checked=$(get_duration "$HAS_LOST_NTP_SYNC" true)
echo "NTP has been unsynced for $duration seconds (last checked $last_checked seconds ago)."
else
echo "NTP state is unknown, ntpd hotplugs might not have been invoked, yet."
fi
* * * * * /usr/sbin/gluon-state-check
#!/usr/bin/lua
local util = require 'gluon.util'
local unistd = require 'posix.unistd'
local state_dir = "/var/gluon/state/"
local check_dir = "/lib/gluon/state/check.d/"
local function set_flag(stateflag, state)
if state then
-- this does not modify atime
local flaghandle = io.open(stateflag, "w")
flaghandle:close()
else
os.remove(stateflag)
end
end
local function exec_check(checkpath)
local checkname = string.sub(checkpath, #check_dir+1)
local ret = os.execute(checkpath)
local flagfile = state_dir..checkname
set_flag(flagfile, 0==ret)
end
local function run_executable_checks()
for _, v in ipairs(util.glob(check_dir..'*')) do
if unistd.access(v, 'x') then
exec_check(v)
end
end
end
-- ensure state path exists
if not unistd.access(state_dir) then
os.execute("mkdir -p "..state_dir)
end
run_executable_checks()
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-status-page-mesh-batman-adv
PKG_VERSION:=1
include ../gluon.mk
......
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-status-page
PKG_VERSION:=3
include ../gluon.mk
......@@ -10,12 +9,20 @@ define Package/gluon-status-page
DEPENDS:=+gluon-web +gluon-neighbour-info +gluon-respondd +uhttpd +sse-multiplex +libiwinfo +libjson-c +libnl-tiny +libubus-lua
endef
PKG_CONFIG_DEPENDS += CONFIG_GLUON_MINIFY
define Package/gluon-status-page/install
$(Gluon/Build/Install)
$(INSTALL_DIR) $(1)/lib/gluon/status-page/providers
$(INSTALL_BIN) $(PKG_BUILD_DIR)/stations $(1)/lib/gluon/status-page/providers/
ifdef CONFIG_GLUON_MINIFY
$(INSTALL_DATA) ./javascript/status-page.min.js $(1)/lib/gluon/status-page/www/static/status-page.js
else
$(INSTALL_DATA) ./javascript/status-page.js $(1)/lib/gluon/status-page/www/static/status-page.js
endif
$(INSTALL_DIR) $(1)/lib/gluon/status-page/view/
$(LN) /lib/gluon/web/i18n $(1)/lib/gluon/status-page/
$(LN) /lib/gluon/web/view/error $(1)/lib/gluon/status-page/view/
......
<%-
http:prepare_content("application/xhtml+xml")
http:prepare_content("text/html")
-%>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<html lang="">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex,nofollow">
<title><%:Error%></title>
<link rel="stylesheet" href="/static/status-page.css" type="text/css" />
<link rel="stylesheet" href="/static/status-page.css" type="text/css">
</head>
<body>
<header>
......
<%-
local iwinfo = require 'iwinfo'
local ubus = require 'ubus'
local unistd = require 'posix.unistd'
local util = require 'gluon.util'
local wireless = require 'gluon.wireless'
local uci = require('simple-uci').cursor()
local translations = {}
local site_i18n = i18n 'gluon-site'
local function _(v)
translations[v] = translate(v)
......@@ -28,17 +33,31 @@
local mesh = get_mesh()
local function get_interfaces()
local uconn = ubus.connect()
if not uconn then
error('failed to connect to ubus')
end
local function get_interfaces(uconn)
local interfaces = util.get_mesh_devices(uconn)
ubus.close(uconn)
table.sort(interfaces)
return interfaces
end
local function get_radios()
local ret = {}
wireless.foreach_radio(uci, function(radio)
local channel = iwinfo.nl80211.channel(wireless.find_phy(radio))
if channel then
table.insert(ret, {
name = radio['.name'],
channel = channel,
})
end
end)
table.sort(ret, function(a, b)
return a.name < b.name
end)
return ret
end
local function is_wireless(iface)
while true do
local pattern = '/sys/class/net/' .. iface .. '/lower_*'
......@@ -48,10 +67,19 @@
iface = lower:sub(pattern:len())
end
return unistd.access('/sys/class/net/' .. iface .. '/wireless') ~= nil
return unistd.access('/sys/class/net/' .. iface .. '/phy80211') ~= nil
end
local interfaces = get_interfaces()
local uconn = ubus.connect()
if not uconn then
error('failed to connect to ubus')
end
local interfaces = get_interfaces(uconn)
ubus.close(uconn)
local radios = get_radios()
local function sorted(t)
t = {unpack(t)}
......@@ -63,29 +91,45 @@
return v and translate('enabled') or translate('disabled')
end
local function formatBits(bits)
local units = {[0]='', 'k', 'M', 'G'}
local unit = 0
for i = 1, #units do
if math.abs(bits) < 1000 then
break
end
unit = i
bits = bits / 1000
end
return string.format('%g %sbit', bits, units[unit])
end
local function statistics(key, format)
return string.format('<span data-statistics="%s" data-format="%s"></span>', pcdata(key), pcdata(format or 'id'))
end
local function statisticsTraffic(key)
return string.format('%s<br />%s<br />%s',
return string.format('%s<br>%s<br>%s',
statistics(key .. '/packets', 'packetsDiff'),
statistics(key .. '/bytes', 'bytesDiff'),
statistics(key .. '/bytes', 'bytes')
)
end
http:prepare_content("application/xhtml+xml")
http:prepare_content("text/html")
-%>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<html lang="">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex,nofollow">
<title><%| nodeinfo.hostname %> - <%:Status%></title>
<link rel="stylesheet" href="/static/status-page.css" type="text/css" />
<link rel="stylesheet" href="/static/status-page.css" type="text/css">
</head>
<body data-node-address="<%| http:getenv('SERVER_ADDR') %>"<%=
attr('data-translations', translations) ..
......@@ -111,10 +155,40 @@
<%- end %>
<dt><%:Model%></dt><dd><%| nodeinfo.hardware.model %></dd>
<dt><%:Primary MAC address%></dt><dd><%| nodeinfo.network.mac %></dd>
<dt><%:IP address%></dt><dd><%= pcdata(table.concat(sorted(nodeinfo.network.addresses), '\n')):gsub('\n', '<br />') %></dd>
<dt><%:IP address%></dt><dd><%= pcdata(table.concat(sorted(nodeinfo.network.addresses), '\n')):gsub('\n', '<br>') %></dd>
<dt><%:Firmware%></dt><dd><%| nodeinfo.software.firmware.release %></dd>
<% if nodeinfo.software.fastd then -%>
<dt><%:Mesh VPN%></dt><dd><%| enabled(nodeinfo.software.fastd.enabled) %></dd>
<% if nodeinfo.network.mesh_vpn then -%>
<dt><%:Mesh VPN%></dt>
<dd>
<%| enabled(nodeinfo.network.mesh_vpn.enabled) %>
<% if nodeinfo.network.mesh_vpn.provider then -%>
<br><%| nodeinfo.network.mesh_vpn.provider %>
<%- end %>
</dd>
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.enabled then -%>
<dt><%:Bandwidth limit%></dt>
<dd>
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.ingress then -%>
<%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.ingress*1000) %>/s <%:downstream%><br>
<%- end %>
<% if nodeinfo.network.mesh_vpn.bandwidth_limit.egress then -%>
<%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.egress*1000) %>/s <%:upstream%>
<%- end %>
</dd>
<%- end %>
<%- end %>
<dt><%:Site%></dt><dd><%| site.site_name() %></dd>
<% if nodeinfo.system.domain_code then -%>
<dt><%:Domain%></dt>
<dd>
<%| site.domain_names[nodeinfo.system.domain_code]() %>
<% if nodeinfo.system.domain_code ~= nodeinfo.system.primary_domain_code then %>
(<%| site.domain_names[nodeinfo.system.primary_domain_code]() %>)
<%- end %>
</dd>
<%- end %>
<% if nodeinfo.system.role then -%>
<dt><%:Role%></dt><dd><%| site_i18n._translate('gluon-web-node-role:role:' .. nodeinfo.system.role) %></dd>
<%- end %>
<% if nodeinfo.software.autoupdater then -%>
<dt><%:Automatic updates%></dt><dd><%| enabled(nodeinfo.software.autoupdater.enabled) %><%|
......@@ -122,33 +196,65 @@
string.format(' (%s)', nodeinfo.software.autoupdater.branch)
%></dd>
<%- end %>
<% if nodeinfo.software['batman-adv'] then -%>
<dt><%:Mesh protocol%></dt>
<% if nodeinfo.software['batman-adv'] then -%>
<dd>batman-adv <%| nodeinfo.software['batman-adv'].version %> (compat<%| nodeinfo.software['batman-adv'].compat %>)</dd>
<%- end %>
<%- end %>
</dl>
</div>
<div class="frame">
<h2><%:Monitoring%></h2>
<table>
<tbody>
<tr><th><%:Uptime%></th><td><%= statistics('uptime', 'time') %></td></tr>
<tr><th><%:Load average%></th><td><%= statistics('loadavg', 'decimal') %></td></tr>
<tr><th><%:RAM%></th><td><%= statistics('memory', 'memory') %></td></tr>
<tr><th><%:Filesystem%></th><td><%= statistics('rootfs_usage', 'percent') %></td></tr>
<tr><th><%:Gateway%></th><td><%= statistics('gateway') %></td></tr>
<tr><th><%:Clients%></th><td><%= statistics('clients/total') %></td></tr>
<tr><th><%:Gateway%></th><td><%= statistics('gateway') %> (TQ: <%= statistics('gateway_tq', 'tq') %>)<br><%= statistics('gateway_nexthop', 'neighbour') %></td></tr>
</tbody>
</table>
<h3><%:Clients%></h3>
<table>
<tbody>
<tr><th><%:Total%></th><td><%= statistics('clients/total') %></td></tr>
<tr><th><%:Wireless 2.4 GHz%></th><td><%= statistics('clients/wifi24') %></td></tr>
<tr><th><%:Wireless 5 GHz%></th><td><%= statistics('clients/wifi5') %></td></tr>
</tbody>
</table>
<% if radios[1] then -%>
<h3><%:Radios%></h3>
<table>
<tbody>
<% for _, radio in ipairs(radios) do -%>
<tr>
<th><%| radio.name %></th>
<td><%| translatef('Channel %u', radio.channel) %></td>
</tr>
<%- end %>
</tbody>
</table>
<%- end %>
<h3><%:Traffic%></h3>
<table>
<tbody>
<tr><th><%:Transmitted%></th><td><%= statisticsTraffic('traffic/tx') %></td></tr>
<tr><th><%:Received%></th><td><%= statisticsTraffic('traffic/rx') %></td></tr>
<tr><th><%:Forwarded%></th><td><%= statisticsTraffic('traffic/forward') %></td></tr>
</tbody>
</table>
<div id="mesh-vpn" style="display: none">
<h3><%:Mesh VPN%></h3>
<table id="mesh-vpn-peers">
<table>
<tbody id="mesh-vpn-peers"></tbody>
</table>
</div>
</div>
<div class="frame">
<div class="frame frame-wide">
<h2><%:Neighbors%></h2>
<%
......@@ -160,17 +266,19 @@
<h3><%| iface %></h3>
<div data-interface="<%| iface %>" data-interface-address="<%| util.trim(address) %>"<%= attr('data-interface-wireless', wireless) %>>
<table class="datatable">
<tbody>
<tr>
<th><%:Node%></th>
<% for i, v in ipairs(mesh.attrs or {}) do %>
<th<%= attr('data-key', v[1]) .. attr('data-suffix', v[3]) %>><%| v[2] %></th>
<th<%= attr('class', 'row-' .. v[1] ) .. attr('data-key', v[1]) .. attr('data-suffix', v[3]) %>><%| v[2] %></th>
<% end %>
<% if wireless then %>
<th>dBm</th>
<th><%:Distance%></th>
<th><%:Last seen%></th>
<th class="row-signal">dBm</th>
<th class="row-distance"><%:Distance%></th>
<th class="row-inactive"><%:Last seen%></th>
<% end %>
</tr>
</tbody>
</table>
</div>
<%
......
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<html lang="">
<head>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="refresh" content="0; URL=/cgi-bin/status" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta http-equiv="refresh" content="0; URL=/cgi-bin/status">
<meta name="robots" content="noindex,nofollow">
</head>
<body>
</body>
......
User-agent: *
Disallow: /
html,body,div,span,h1,h2,h3,dl,dt,dd,canvas,header,table,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body{background:rgba(0,0,0,0.12);font-family:Roboto, Lucida Grande, sans, Arial;color:rgba(0,0,0,0.87);font-size:14px;line-height:1}a{color:rgba(220,0,103,0.87);text-decoration:none;margin:0;padding:0;font-size:100%;vertical-align:baseline;background:transparent}a:hover{text-decoration:underline}h1{font-weight:bold}h2{font-size:16px;margin-bottom:16px;color:rgba(0,0,0,0.54)}h3{font-size:15px;margin-top:16px;margin-bottom:8px;color:rgba(0,0,0,0.54)}header{display:flex;padding:0 14px;background:#dc0067;color:rgba(255,255,255,0.98);position:absolute;top:0;width:100%;box-sizing:border-box;height:20vh;z-index:-1;box-shadow:0px 5px 6px rgba(0,0,0,0.16),0px 1.5px 3px rgba(0,0,0,0.23);white-space:nowrap}header h1{font-size:24px;margin:10px 0;padding:6px 0;text-overflow:ellipsis;overflow:hidden;flex:1}.container{display:flex;max-width:90vw;margin:64px auto 24px auto;background:#fdfdfd;box-shadow:0px 5px 20px rgba(0,0,0,0.19),0px 3px 6px rgba(0,0,0,0.23)}.container>.frame{flex:1;border-style:solid;border-color:rgba(0,0,0,0.12);box-sizing:border-box;padding:16px}.container>.frame+.frame{border-width:0 0 0 1px}dt,th{font-weight:bold;color:rgba(0,0,0,0.87)}dt{margin-bottom:4px}th,td{text-align:left;padding:4px 16px 4px 0}th:last-child,td:last-child{padding-right:0}dd,td{font-weight:normal;font-size:0.9em;color:rgba(0,0,0,0.54)}dd{margin-bottom:16px}table{border-collapse:collapse;border-spacing:0}table.datatable{width:100%}table.datatable th,table.datatable td{font-size:1em;white-space:nowrap}table.datatable th:last-child,table.datatable td:last-child{width:100%}table.datatable tr.inactive{opacity:0.33}table.datatable tr.highlight{background:rgba(255,180,0,0.25)}canvas.signalgraph{margin-top:8px;width:100%}@media only screen and (max-width: 1250px){.container{max-width:none;margin:56px 0 0}header{height:56px;z-index:1;position:fixed}}@media only screen and (max-width: 700px){.container{display:block}.container>.frame+.frame{border-width:1px 0 0 0}}
html,body,div,span,h1,h2,h3,dl,dt,dd,canvas,header,table,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body{background:rgba(0,0,0,0.12);font-family:Roboto, Lucida Grande, sans, Arial;color:rgba(0,0,0,0.87);font-size:14px;line-height:1}a{color:rgba(220,0,103,0.87);text-decoration:none;margin:0;padding:0;font-size:100%;vertical-align:baseline;background:transparent}a:hover{text-decoration:underline}h1{font-weight:bold}h2{font-size:16px;margin-bottom:16px;color:rgba(0,0,0,0.54)}h3{font-size:15px;margin-top:16px;margin-bottom:8px;color:rgba(0,0,0,0.54)}header{display:flex;padding:0 14px;background:#dc0067;color:rgba(255,255,255,0.98);position:absolute;top:0;width:100%;box-sizing:border-box;height:20vh;z-index:-1;box-shadow:0px 5px 6px rgba(0,0,0,0.16),0px 1.5px 3px rgba(0,0,0,0.23);white-space:nowrap}header h1{font-size:24px;margin:10px 0;padding:6px 0;text-overflow:ellipsis;overflow:hidden;flex:1}.container{display:flex;max-width:90vw;margin:64px auto 24px auto;background:#fdfdfd;box-shadow:0px 5px 20px rgba(0,0,0,0.19),0px 3px 6px rgba(0,0,0,0.23)}.container>.frame{flex:1;border-style:solid;border-color:rgba(0,0,0,0.12);box-sizing:border-box;padding:16px}.container>.frame+.frame{border-width:0 0 0 1px}.container>.frame-wide{flex:2}dt,th,td::before{font-weight:bold;color:rgba(0,0,0,0.87)}dt{margin-bottom:4px}th,td{text-align:left;padding:4px 16px 4px 0}th:last-child,td:last-child{padding-right:0}dd,td{font-weight:normal;font-size:0.9em;color:rgba(0,0,0,0.54)}dd{margin-bottom:16px}table{border-collapse:collapse;border-spacing:0}table.datatable{width:100%;table-layout:fixed}table.datatable th,table.datatable td{font-size:1em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}table.datatable th.row-tq{width:45px}table.datatable th.row-signal{width:36px}table.datatable th.row-distance{width:90px}table.datatable th.row-inactive{width:130px}table.datatable tr.inactive{opacity:0.33}table.datatable tr.highlight{background:rgba(255,180,0,0.25)}canvas.signalgraph{margin-top:8px;width:100%}@media only screen and (max-width: 1250px){.container{max-width:none;margin:56px 0 0}header{height:56px;z-index:1;position:fixed}.datatable tr{display:block;margin-bottom:15px}.datatable tr:first-child{margin-bottom:0}.datatable th{display:none}.datatable td{display:block;position:relative;padding-left:150px;max-width:calc(100% - 150px)}.datatable td::before{position:absolute;left:5px;content:attr(data-label)}}@media only screen and (max-width: 700px){.container{display:block}.container>.frame+.frame{border-width:1px 0 0 0}}
"use strict";!function(){var a=JSON.parse(document.body.getAttribute("data-translations"));function r(t,e){return t.toFixed(e).replace(/\./,a["."])}function o(t,e){e--;for(var n=t;10<=n&&0<e;n/=10)e--;return r(t,e)}function i(t){return function(t,e,n){var i=0;if(void 0===n)return"- ";for(;e<n&&i<t.length-1;)n/=e,i++;return(n=o(n,3))+" "+t[i]}(["","K","M","G","T"],1024,t)}String.prototype.sprintf=function(){var t=0,e=arguments;return this.replace(/%s/g,function(){return e[t++]})};var u={id:function(t){return t},decimal:function(t){return r(t,2)},percent:function(t){return a["%s used"].sprintf(o(100*t,3)+"%")},memory:function(t){var e=1-t.available/t.total;return u.percent(e)},time:function(t){var e=Math.round(t/60),n=Math.floor(e/1440),i=Math.floor(e%1440/60);e=Math.floor(e%60);var r="";return 1===n?r+=a["1 day"]+", ":1<n&&(r+=a["%s days"].sprintf(n)+", "),r+=i+":",e<10&&(r+="0"),r+=e},packetsDiff:function(t,e,n){if(0<n)return i=(t-e)/n,a["%s packets/s"].sprintf(r(i,0));var i},bytesDiff:function(t,e,n){if(0<n)return i(8*((t-e)/n))+"bps"},bytes:function(t){return i(t)+"B"}};function l(e,t){return t.split("/").forEach(function(t){e&&(e=e[t])}),e}function f(t,n){var e=new EventSource(t),i={};e.onmessage=function(t){var e=JSON.parse(t.data);n(e,i),i=e},e.onerror=function(){e.close(),window.setTimeout(function(){f(t,n)},3e3)}}var y,C=document.body.getAttribute("data-node-address");try{y=JSON.parse(document.body.getAttribute("data-node-location"))}catch(t){}var t=document.querySelectorAll("[data-statistics]");f("/cgi-bin/dyn/statistics",function(o,c){var s=o.uptime-c.uptime;t.forEach(function(t){var e=t.getAttribute("data-statistics"),n=t.getAttribute("data-format"),i=l(c,e),r=l(o,e);try{var a=u[n](r,i,s);void 0!==a&&(t.textContent=a)}catch(t){console.error(t)}});try{!function(t){var e=document.getElementById("mesh-vpn");if(t){e.style.display="";for(var r=document.getElementById("mesh-vpn-peers");r.lastChild;)r.removeChild(r.lastChild);var n=function e(n,i){return Object.keys(i.peers||{}).forEach(function(t){n.push([t,i.peers[t]])}),Object.keys(i.groups||{}).forEach(function(t){e(n,i.groups[t])}),n}([],t);n.sort(),n.forEach(function(t){var e=document.createElement("tr"),n=document.createElement("th");n.textContent=t[0],e.appendChild(n);var i=document.createElement("td");t[1]?i.textContent=a.connected+" ("+u.time(t[1].established)+")":i.textContent=a["not connected"],e.appendChild(i),r.appendChild(e)})}else e.style.display="none"}(o.mesh_vpn)}catch(t){console.error(t)}});var c={};function w(a){var o=document.createElement("canvas"),c=o.getContext("2d"),s=null;return{canvas:o,highlight:!1,resize:function(t,e){try{c.getImageData(0,0,t,e)}catch(t){}o.width=t,o.height=e},draw:function(t,e){var n,i,r=e(s);c.clearRect(t,0,5,o.height),r&&(n=t,i=r,c.beginPath(),c.fillStyle=a,c.arc(n,i,1.2,0,2*Math.PI,!1),c.closePath(),c.fill())},set:function(t){s=t}}}function h(){var s=-100,u=0,n=0,i=[],l=document.createElement("canvas");l.className="signalgraph",l.height=200;var f=l.getContext("2d");function t(){l.width=l.clientWidth,i.forEach(function(t){t.resize(l.width,l.height)})}function r(){if(0!==l.clientWidth){l.width!==l.clientWidth&&t(),f.clearRect(0,0,l.width,l.height);var e=!1;i.forEach(function(t){t.highlight&&(e=!0)}),f.save(),i.forEach(function(t){e&&(f.globalAlpha=.2),t.highlight&&(f.globalAlpha=1),t.draw(n,function(t){return e=t,n=s,i=u,r=l.height,(1-(e-n)/(i-n))*r;var e,n,i,r}),f.drawImage(t.canvas,0,0)}),f.restore(),f.save(),f.beginPath(),f.strokeStyle="rgba(255, 180, 0, 0.15)",f.lineWidth=5,f.moveTo(n+2.5,0),f.lineTo(n+2.5,l.height),f.stroke(),function(){var t,e,n,i,r=Math.floor(l.height/40);f.save(),f.lineWidth=.5,f.strokeStyle="rgba(0, 0, 0, 0.25)",f.fillStyle="rgba(0, 0, 0, 0.5)",f.textAlign="end",f.textBaseline="bottom",f.beginPath();for(var a=0;a<r;a++){var o=l.height-40*a;f.moveTo(0,o-.5),f.lineTo(l.width,o-.5);var c=Math.round((t=o,e=s,n=u,i=l.height,(e*t+n*(i-t))/i))+" dBm";f.save(),f.strokeStyle="rgba(255, 255, 255, 0.9)",f.lineWidth=4,f.miterLimit=2,f.strokeText(c,l.width-5,o-2.5),f.fillText(c,l.width-5,o-2.5),f.restore()}f.stroke(),f.strokeStyle="rgba(0, 0, 0, 0.83)",f.lineWidth=1.5,f.strokeRect(.5,.5,l.width-1,l.height-1),f.restore()}()}}t(),window.addEventListener("resize",r);var a=0;return window.requestAnimationFrame(function t(e){40<e-a&&(r(),n=(n+1)%l.width,a=e),window.requestAnimationFrame(t)}),{el:l,addSignal:function(t){i.push(t),t.resize(l.width,l.height)},removeSignal:function(t){i.splice(i.indexOf(t),1)}}}function d(t,e,n,i){var r=t.table.firstElementChild,a=t.table.insertRow(),o=a.insertCell();if(t.wireless){var c=document.createElement("span");c.textContent="",c.style.color=n,o.appendChild(c)}var h=document.createElement("span");h.textContent=e,o.appendChild(h);var s,d,u,l,f,v={};function g(t){var e=t.getAttribute("data-key");if(e){var n=t.getAttribute("data-suffix")||"",i=a.insertCell();i.textContent="-",v[e]={td:i,suffix:n}}}for(var m=0;m<r.children.length;m++)g(r.children[m]);function p(){f&&window.clearTimeout(f),f=window.setTimeout(function(){l&&t.signalgraph.removeSignal(l),a.parentNode.removeChild(a),i()},6e4)}function b(t){var e=function(t){"::"==t.slice(0,2)&&(t="0"+t),"::"==t.slice(-2)&&(t+="0");var e=t.split(":"),n=e.length,i=[];return e.forEach(function(t,e){if(""===t)for(;n++<=8;)i.push(0);else{if(!/^[a-f0-9]{1,4}$/i.test(t))return;i.push(parseInt(t,16))}}),i}(t);if(e){var n="";return e.forEach(function(t){n+=("0000000000000000"+t.toString(2)).slice(-16)}),n}}return t.wireless&&((s=a.insertCell()).textContent="-",(d=a.insertCell()).textContent="-",(u=a.insertCell()).textContent="-",l=w(n),t.signalgraph.addSignal(l)),a.onmouseenter=function(){a.classList.add("highlight"),l&&(l.highlight=!0)},a.onmouseleave=function(){a.classList.remove("highlight"),l&&(l.highlight=!1)},p(),{update_nodeinfo:function(t){var e,n,i,r,a,o,c,s,u=function(t){var i=b(C);if(t&&t[0]){(t=t.map(function(t){var e=b(t);if(!e)return[-1];var n=0;return i&&(n=function(t,e){var n;for(n=0;n<t.length&&n<e.length&&t[n]===e[n];n++);return n}(i,e)),[n,e,t]})).sort(function(t,e){return t[0]<e[0]?1:t[0]>e[0]?-1:t[1]<e[1]?-1:t[1]>e[1]?1:0});var e=t[0][2];return e&&!/^fe80:/i.test(e)?e:void 0}}(t.network.addresses);if(u){if("span"===h.nodeName.toLowerCase()){var l=h;h=document.createElement("a"),l.parentNode.replaceChild(h,l)}h.href="http://["+u+"]/"}if(h.textContent=t.hostname,y&&t.location){var f=(e=y.latitude,n=y.longitude,i=t.location.latitude,r=t.location.longitude,a=Math.PI/180,o=(i*=a)-(e*=a),c=(r*=a)-(n*=a),s=Math.sin(o/2)*Math.sin(o/2)+Math.sin(c/2)*Math.sin(c/2)*Math.cos(e)*Math.cos(i),2*Math.asin(Math.sqrt(s))*6372.8);d.textContent=Math.round(1e3*f)+" m"}p()},update_mesh:function(n){Object.keys(v).forEach(function(t){var e=v[t];e.td.textContent=n[t]+e.suffix}),p()},update_wifi:function(t){s.textContent=t.signal,u.textContent=Math.round(t.inactive/1e3)+" s",a.classList.toggle("inactive",200<t.inactive),l.set(200<t.inactive?null:t.signal),p()}}}function s(t,e,n){var i,a={};n&&(i=h(),t.appendChild(i.el));var r={table:t.firstElementChild,signalgraph:i,ifname:e,wireless:n},o=!1,c={},s=[];function u(){if(!o){o=!0;var t=new EventSource("/cgi-bin/dyn/neighbours-nodeinfo?"+encodeURIComponent(e));t.addEventListener("neighbour",function(t){try{var n=JSON.parse(t.data);(e=n,i=[],r=e.network.mesh,Object.keys(r).forEach(function(t){var e=r[t].interfaces;Object.keys(e).forEach(function(t){e[t].forEach(function(t){i.push(t)})})}),i).forEach(function(t){var e=a[t];if(e){delete c[t];try{e.update_nodeinfo(n)}catch(t){console.error(t)}}})}catch(t){console.error(t)}var e,i,r},!1),t.onerror=function(){t.close(),o=!1,Object.keys(c).forEach(function(t){0<c[t]&&(c[t]--,u())})}}}function l(t){var e=a[t];return e||(c[t]=3,e=a[t]=d(r,t,(s[0]||(s=["#396AB1","#DA7C30","#3E9651","#CC2529","#535154","#6B4C9A","#922428","#948B3D"]),s.shift()),function(){delete c[t],delete a[t]}),u()),e}return n&&f("/cgi-bin/dyn/stations?"+encodeURIComponent(e),function(n){Object.keys(n).forEach(function(t){var e=n[t];l(t).update_wifi(e)})}),{get_neigh:l}}document.querySelectorAll("[data-interface]").forEach(function(t){var e=t.getAttribute("data-interface"),n=(t.getAttribute("data-interface-address"),!!t.getAttribute("data-interface-wireless"));c[e]=s(t,e,n)});var e=document.body.getAttribute("data-mesh-provider");e&&f(e,function(i){Object.keys(i).forEach(function(t){var e=i[t],n=c[e.ifname];n&&n.get_neigh(t).update_mesh(e)})})}();
\ No newline at end of file
#!/bin/sh
# shellcheck source=package/gluon-autoupdater/files/lib/gluon/autoupdater/lib.sh
. /lib/gluon/autoupdater/lib.sh
......
#!/bin/sh
# shellcheck source=package/gluon-autoupdater/files/lib/gluon/autoupdater/lib.sh
. /lib/gluon/autoupdater/lib.sh
......
......@@ -28,18 +28,27 @@ msgstr "1 Tag"
msgid "Automatic updates"
msgstr "Automatische Updates"
msgid "Bandwidth limit"
msgstr "Bandbreitenlimit"
msgid "Channel %u"
msgstr "Kanal %u"
msgid "Clients"
msgstr "Clients"
msgid "Contact"
msgstr "Kontakt"
msgid "Location"
msgstr "Position"
msgid "Distance"
msgstr "Entfernung"
msgid "Domain"
msgstr "Domäne"
msgid "downstream"
msgstr "Downstream"
msgid "Error"
msgstr "Fehler"
......@@ -64,6 +73,12 @@ msgstr "Zuletzt gesehen"
msgid "Load average"
msgstr "Systemlast"
msgid "Location"
msgstr "Position"
msgid "Mesh protocol"
msgstr "Mesh-Protokoll"
msgid "Mesh VPN"
msgstr "Mesh-VPN"
......@@ -88,24 +103,45 @@ msgstr "Übersicht"
msgid "Primary MAC address"
msgstr "Primäre MAC-Adresse"
msgid "Radios"
msgstr ""
msgid "RAM"
msgstr "RAM"
msgid "Received"
msgstr "Empfangen"
msgid "Role"
msgstr "Rolle"
msgid "Site"
msgstr "Site"
msgid "Status"
msgstr "Status"
msgid "Total"
msgstr "Gesamt"
msgid "Traffic"
msgstr ""
msgid "Transmitted"
msgstr "Gesendet"
msgid "upstream"
msgstr "Upstream"
msgid "Uptime"
msgstr "Laufzeit"
msgid "Wireless 2.4 GHz"
msgstr ""
msgid "Wireless 5 GHz"
msgstr ""
msgid "connected"
msgstr "verbunden"
......@@ -117,3 +153,6 @@ msgstr "aktiviert"
msgid "not connected"
msgstr "nicht verbunden"
#~ msgid "Gateway Nexthop"
#~ msgstr "Gateway Nexthop"