Add network information

This commit is contained in:
Jannik Beyerstedt 2023-04-17 20:49:53 +02:00
parent ae6ea74cbb
commit 16e0fd5a07
5 changed files with 149 additions and 10 deletions

4
Readme.md Normal file
View file

@ -0,0 +1,4 @@
# info-beamer testcard
Screen test card with additional information for https://info-beamer.com.
This is a modified version of https://git.franzi.business/kunsi/infobeamer-testcard, which adds network connectivity information (taken from the [Screen Installation Instructions](https://github.com/info-beamer/package-installation-help) package).

View file

@ -1,7 +1,9 @@
{ {
"name": "c3voc testcard", "name": "Screen Testcard",
"options": [], "options": [],
"permissions": { "permissions": {
"network": "Needs to fetch device info from info-beamer api" "network": "Needs to fetch device info from info-beamer api",
"unboxed": "Needs access to the device configuration",
"run-as-root": "Needs access to /sd/config"
} }
} }

View file

@ -1,3 +1,4 @@
node.alias "testcard"
util.init_hosted() util.init_hosted()
local json = require "json" local json = require "json"
@ -19,6 +20,19 @@ gl.setup(NATIVE_WIDTH, NATIVE_HEIGHT)
card = resource.load_image("testcard.png") card = resource.load_image("testcard.png")
font = resource.load_font("vera.ttf") font = resource.load_font("vera.ttf")
local v = {
network = "<unkown>",
ethip = "<unkown>",
wlanip = "<unkown>",
gw = "<unkown>"
}
util.data_mapper{
["update/(.*)"] = function(key, val)
v[key] = val
end
}
function node.render() function node.render()
gl.clear(0,0,0,1) gl.clear(0,0,0,1)
@ -27,7 +41,7 @@ function node.render()
-- upper: 623 -- upper: 623
-- lower: 707 -- lower: 707
upper_text = "C3VOC: " .. description upper_text = "CCC: " .. description
if location == nil or location == '' then if location == nil or location == '' then
lower_text = "Serial " .. serial lower_text = "Serial " .. serial
@ -40,4 +54,35 @@ function node.render()
lower_width = font:width(lower_text, 20) lower_width = font:width(lower_text, 20)
font:write(960-(lower_width/2), 679, lower_text, 20, 1,1,1,1) font:write(960-(lower_width/2), 679, lower_text, 20, 1,1,1,1)
-- draw text on left and right dark grey area
local fontsize = 30
local offset = fontsize+10
local x_left = 100
local x_right = 1430
local y_start = 500
-- left side: network config, online status
local y = y_start
font:write(x_left, y, "Mode: " .. v.network, fontsize, 1,1,1,1)
y = y + offset
font:write(x_left, y, "GW: " .. v.gw, fontsize, 1,1,1,1)
y = y + offset
if v.online then
local col = {1,0,0,1}
if v.online == "online" then
col = {0,1,0,1}
end
font:write(x_left, y, v.online, fontsize, unpack(col))
end
-- right side: IP addresses
y = y_start
font:write(x_right, y, "Eth: " .. v.ethip, fontsize, 1,1,1,1)
y = y + offset
font:write(x_right, y, "WiFi: " .. v.wlanip, fontsize, 1,1,1,1)
end end

View file

@ -1,8 +1,8 @@
{ {
"name": "c3voc testcard", "name": "Info-beamer Testcard",
"author": "Kunsi <kunsi@c3voc.de>", "author": "Jannik Beyerstedt <code@jbeyerstedt.de>",
"desc": "testcard", "desc": "testcard",
"repository": "https://git.kunsmann.eu/kunsi/icinga2beamer", "repository": "https://git.beyerstedt.de/jannik/infobeamer-testcard",
"nesting": { "nesting": {
"parents": [ "parents": [
"top-level" "top-level"

92
service
View file

@ -1,12 +1,22 @@
#!/usr/bin/python #!/usr/bin/python
import os
import sys import sys
import fcntl
import socket
import struct
import requests
import time import time
import traceback import traceback
from functools import partial
from heapq import heappush, heapreplace
from hosted import api, node from hosted import api, node
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def fetch_info(): def fetch_info():
info = api.device_info.get() info = api.device_info.get()
print >> sys.stderr, info print >> sys.stderr, info
@ -18,11 +28,89 @@ def fetch_info():
) )
def send(key, val):
sys.stderr.write("sending %s->%s\n" % (key, val))
sock.sendto('testcard/update/%s:%s' % (key, val), ('127.0.0.1', 4444))
def get_default_gateway():
with open("/proc/net/route") as fh:
for line in fh:
fields = line.strip().split()
if fields[1] != '00000000' or not int(fields[3], 16) & 2:
continue
return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))
def get_ipv4(ifname):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8915,
struct.pack('256s', ifname[:15]))
ip = socket.inet_ntoa(info[20:24])
mask = struct.unpack('>I', fcntl.ioctl(
s.fileno(), 0x891b, struct.pack('256s', ifname))[20:24])[0]
# Remember: not everything has to be performance optimal :-)
mask = bin(mask)[2:].count('1')
return "%s/%d" % (ip, mask)
except IOError:
return "<no ipv4>"
except:
return None
def check_network():
return os.path.exists('/sd/config/network') and "static" or "dhcp"
def check_internet():
try:
r = requests.get("http://ping.infobeamer.com/ping", timeout=10, headers={
'User-Agent': 'info-beamer syncer/network-check',
})
r.raise_for_status()
if r.content == "pong":
return "online"
else:
return "filtered"
except:
traceback.print_exc()
return "offline"
tests = [
(1, "ethip", partial(get_ipv4, "eth0")),
(1, "wlanip", partial(get_ipv4, "wlan0")),
(1, "gw", get_default_gateway),
(10, "online", check_internet),
(5, "network", check_network),
]
q = []
now = time.time()
for interval, key, val_fn in tests:
heappush(q, (now, (interval, key, val_fn)))
def run_next_test():
now = time.time()
t, test = q[0]
if now < t:
return False
interval, key, val_fn = test
heapreplace(q, (now + interval, test))
val = val_fn()
if val is not None:
send(key, val)
return True
if __name__ == "__main__": if __name__ == "__main__":
while 1: while 1:
try: try:
fetch_info() fetch_info()
if not run_next_test():
time.sleep(0.5)
except: except:
traceback.print_exc() traceback.print_exc()
finally:
time.sleep(15)