diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..5e9152d --- /dev/null +++ b/Readme.md @@ -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). diff --git a/node.json b/node.json index 2ebd077..f4dc52f 100644 --- a/node.json +++ b/node.json @@ -1,7 +1,9 @@ { - "name": "c3voc testcard", + "name": "Screen Testcard", "options": [], "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" } -} +} \ No newline at end of file diff --git a/node.lua b/node.lua index 80ba863..494b1d9 100644 --- a/node.lua +++ b/node.lua @@ -1,3 +1,4 @@ +node.alias "testcard" util.init_hosted() local json = require "json" @@ -19,6 +20,19 @@ gl.setup(NATIVE_WIDTH, NATIVE_HEIGHT) card = resource.load_image("testcard.png") font = resource.load_font("vera.ttf") +local v = { + network = "", + ethip = "", + wlanip = "", + gw = "" +} + +util.data_mapper{ + ["update/(.*)"] = function(key, val) + v[key] = val + end +} + function node.render() gl.clear(0,0,0,1) @@ -27,7 +41,7 @@ function node.render() -- upper: 623 -- lower: 707 - upper_text = "C3VOC: " .. description + upper_text = "CCC: " .. description if location == nil or location == '' then lower_text = "Serial " .. serial @@ -40,4 +54,35 @@ function node.render() lower_width = font:width(lower_text, 20) 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 diff --git a/package.json b/package.json index e6b3e79..d57fedb 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "c3voc testcard", - "author": "Kunsi ", + "name": "Info-beamer Testcard", + "author": "Jannik Beyerstedt ", "desc": "testcard", - "repository": "https://git.kunsmann.eu/kunsi/icinga2beamer", + "repository": "https://git.beyerstedt.de/jannik/infobeamer-testcard", "nesting": { "parents": [ "top-level" @@ -17,4 +17,4 @@ "support": "no", "info": "Needs to fetch information about itself from info-beamer api" } -} +} \ No newline at end of file diff --git a/service b/service index fd5c80f..7cb2d04 100644 --- a/service +++ b/service @@ -1,12 +1,22 @@ #!/usr/bin/python +import os import sys +import fcntl +import socket +import struct +import requests import time import traceback +from functools import partial +from heapq import heappush, heapreplace from hosted import api, node +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + def fetch_info(): info = api.device_info.get() 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("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 "" + 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__": while 1: try: fetch_info() + if not run_next_test(): + time.sleep(0.5) except: traceback.print_exc() - finally: - time.sleep(15)