WIP: Add network information

This commit is contained in:
Jannik Beyerstedt 2023-04-17 20:49:53 +02:00
parent ae6ea74cbb
commit accc4219cf
5 changed files with 160 additions and 8 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,14 @@ 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 = {}
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 +36,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 +49,51 @@ 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)
-- TODO
local size, k_x, v_x, y
size = math.floor(HEIGHT/20)
y = 30+size*6
k_x, v_x = 30, 30+font:width("XXXXXXXXXXXXXXXX", size)
util.draw_correct(logo, 30, 30, WIDTH/2-30, 30+size*5)
gray:draw(WIDTH/2-1, 0, WIDTH/2+1, HEIGHT)
local function key(str)
font:write(k_x, y, str, size, 1,1,1,.5)
end
local function val(str, col)
col = col or {1,1,1,.5}
font:write(v_x, y, str, size, unpack(col))
y = y + size*1.1
end
if v.network then
key "Network config"
val(v.network)
end
if v.ethip then
key "Ethernet IPv4"
val(v.ethip)
end
if v.wlanip then
key "WiFi IPv4"
val(v.wlanip)
end
if v.gw then
key "Gateway"
val(v.gw)
end
if v.online then
key "Online status"
local col = {1,0,0,1}
if v.online == "online" then
col = {0,1,0,1}
end
val(v.online, col)
end
end end

View file

@ -1,8 +1,8 @@
{ {
"name": "c3voc testcard", "name": "infobeamer-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"

90
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,10 +28,90 @@ 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.2)
except: except:
traceback.print_exc() traceback.print_exc()
finally: finally: