Dateien nach „/“ hochladen
This commit is contained in:
parent
a76a91b0a4
commit
d393d4263e
1 changed files with 577 additions and 0 deletions
577
down.py
Normal file
577
down.py
Normal file
|
|
@ -0,0 +1,577 @@
|
|||
from PIL import Image, ImageDraw, ImageFont
|
||||
import numpy as np
|
||||
import time
|
||||
import socket
|
||||
import fcntl
|
||||
import struct
|
||||
import traceback
|
||||
import urllib.request
|
||||
|
||||
from zoneinfo import ZoneInfo
|
||||
from influxdb_client import InfluxDBClient
|
||||
|
||||
# -------------------------------------------------
|
||||
# InfluxDB V2
|
||||
# -------------------------------------------------
|
||||
|
||||
INFLUX_URL = "http://10.0.1.134:9086"
|
||||
INFLUX_TOKEN = "QSFzWhbpLI71fPiSfINDmtI3YkO4PgdTjyen_zxLzUe45vaVlUbAB04gV75wZjrfWV0WTIGQTv1F3_G0mTdIgQ=="
|
||||
INFLUX_ORG = "iobroker"
|
||||
INFLUX_BUCKET = "hintergasse"
|
||||
|
||||
# -------------------------------------------------
|
||||
# Display
|
||||
# -------------------------------------------------
|
||||
|
||||
WIDTH = 480
|
||||
HEIGHT = 320
|
||||
FB = "/dev/fb0"
|
||||
|
||||
# -------------------------------------------------
|
||||
# Fonts
|
||||
# -------------------------------------------------
|
||||
|
||||
font_title = ImageFont.truetype(
|
||||
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
|
||||
22
|
||||
)
|
||||
|
||||
font_small = ImageFont.truetype(
|
||||
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
||||
18
|
||||
)
|
||||
|
||||
font_small_bold = ImageFont.truetype(
|
||||
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
|
||||
18
|
||||
)
|
||||
|
||||
font_download = ImageFont.truetype(
|
||||
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
|
||||
46
|
||||
)
|
||||
|
||||
font_upload = ImageFont.truetype(
|
||||
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
|
||||
34
|
||||
)
|
||||
|
||||
font_delta = ImageFont.truetype(
|
||||
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
||||
16
|
||||
)
|
||||
|
||||
# -------------------------------------------------
|
||||
# Lokale WLAN-IP
|
||||
# -------------------------------------------------
|
||||
|
||||
def get_ip():
|
||||
|
||||
interfaces = ["wlan0", "wlp2s0", "wlan1"]
|
||||
|
||||
for interface in interfaces:
|
||||
|
||||
try:
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
ip = socket.inet_ntoa(
|
||||
fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8915,
|
||||
struct.pack(
|
||||
'256s',
|
||||
interface[:15].encode('utf-8')
|
||||
)
|
||||
)[20:24]
|
||||
)
|
||||
|
||||
return ip
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
return "Keine WLAN-IP"
|
||||
|
||||
# -------------------------------------------------
|
||||
# Öffentliche WAN-IP
|
||||
# -------------------------------------------------
|
||||
|
||||
def get_wan_ip():
|
||||
|
||||
try:
|
||||
|
||||
with urllib.request.urlopen(
|
||||
"https://api.ipify.org",
|
||||
timeout=5
|
||||
) as response:
|
||||
|
||||
return response.read().decode("utf-8")
|
||||
|
||||
except:
|
||||
|
||||
return "Keine WAN-IP"
|
||||
|
||||
# -------------------------------------------------
|
||||
# Ping aus InfluxDB lesen
|
||||
# -------------------------------------------------
|
||||
|
||||
def get_ping():
|
||||
|
||||
try:
|
||||
|
||||
client = InfluxDBClient(
|
||||
url=INFLUX_URL,
|
||||
token=INFLUX_TOKEN,
|
||||
org=INFLUX_ORG
|
||||
)
|
||||
|
||||
query_api = client.query_api()
|
||||
|
||||
query = f'''
|
||||
from(bucket: "{INFLUX_BUCKET}")
|
||||
|> range(start: -24h)
|
||||
|> filter(fn: (r) => r["_measurement"] == "speedtest")
|
||||
|> filter(fn: (r) => r["_field"] == "ping")
|
||||
|> last()
|
||||
'''
|
||||
|
||||
tables = query_api.query(query)
|
||||
|
||||
for table in tables:
|
||||
|
||||
for record in table.records:
|
||||
|
||||
return float(record.get_value())
|
||||
|
||||
except:
|
||||
|
||||
pass
|
||||
|
||||
return -1
|
||||
|
||||
# -------------------------------------------------
|
||||
# Verlauf der letzten Downloads
|
||||
# -------------------------------------------------
|
||||
|
||||
def get_download_history():
|
||||
|
||||
try:
|
||||
|
||||
client = InfluxDBClient(
|
||||
url=INFLUX_URL,
|
||||
token=INFLUX_TOKEN,
|
||||
org=INFLUX_ORG
|
||||
)
|
||||
|
||||
query_api = client.query_api()
|
||||
|
||||
query = f'''
|
||||
from(bucket: "{INFLUX_BUCKET}")
|
||||
|> range(start: -24h)
|
||||
|> filter(fn: (r) => r["_measurement"] == "speedtest")
|
||||
|> filter(fn: (r) => r["_field"] == "download_bits")
|
||||
|> sort(columns: ["_time"])
|
||||
'''
|
||||
|
||||
tables = query_api.query(query)
|
||||
|
||||
values = []
|
||||
|
||||
for table in tables:
|
||||
|
||||
for record in table.records:
|
||||
|
||||
value = record.get_value()
|
||||
|
||||
if value is not None:
|
||||
|
||||
values.append(
|
||||
value / 1000 / 1000
|
||||
)
|
||||
|
||||
return values[-24:]
|
||||
|
||||
except Exception:
|
||||
|
||||
print(traceback.format_exc())
|
||||
|
||||
return []
|
||||
|
||||
# -------------------------------------------------
|
||||
# Speedtest aus InfluxDB lesen
|
||||
# -------------------------------------------------
|
||||
|
||||
def get_speedtest():
|
||||
|
||||
try:
|
||||
|
||||
client = InfluxDBClient(
|
||||
url=INFLUX_URL,
|
||||
token=INFLUX_TOKEN,
|
||||
org=INFLUX_ORG
|
||||
)
|
||||
|
||||
query_api = client.query_api()
|
||||
|
||||
# DOWNLOAD
|
||||
|
||||
query_down = f'''
|
||||
from(bucket: "{INFLUX_BUCKET}")
|
||||
|> range(start: -24h)
|
||||
|> filter(fn: (r) => r["_measurement"] == "speedtest")
|
||||
|> filter(fn: (r) => r["_field"] == "download_bits")
|
||||
|> tail(n: 2)
|
||||
'''
|
||||
|
||||
result_down = query_api.query(query_down)
|
||||
|
||||
down = 0
|
||||
down_prev = 0
|
||||
|
||||
timestamp = "Keine Daten"
|
||||
|
||||
download_values = []
|
||||
|
||||
for table in result_down:
|
||||
|
||||
for record in table.records:
|
||||
|
||||
download_values.append(
|
||||
record.get_value()
|
||||
)
|
||||
|
||||
local_time = record.get_time().astimezone(
|
||||
ZoneInfo("Europe/Berlin")
|
||||
)
|
||||
|
||||
if len(download_values) >= 1:
|
||||
down = download_values[-1]
|
||||
|
||||
if len(download_values) >= 2:
|
||||
down_prev = download_values[-2]
|
||||
|
||||
now = time.localtime()
|
||||
|
||||
today = (
|
||||
local_time.year == now.tm_year and
|
||||
local_time.month == now.tm_mon and
|
||||
local_time.day == now.tm_mday
|
||||
)
|
||||
|
||||
yesterday_ts = time.time() - 86400
|
||||
yesterday = time.localtime(yesterday_ts)
|
||||
|
||||
is_yesterday = (
|
||||
local_time.year == yesterday.tm_year and
|
||||
local_time.month == yesterday.tm_mon and
|
||||
local_time.day == yesterday.tm_mday
|
||||
)
|
||||
|
||||
if today:
|
||||
|
||||
timestamp = local_time.strftime(
|
||||
"HEUTE %H:%M"
|
||||
)
|
||||
|
||||
elif is_yesterday:
|
||||
|
||||
timestamp = local_time.strftime(
|
||||
"GESTERN %H:%M"
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
timestamp = local_time.strftime(
|
||||
"%d.%m.%Y %H:%M"
|
||||
)
|
||||
|
||||
# UPLOAD
|
||||
|
||||
query_up = f'''
|
||||
from(bucket: "{INFLUX_BUCKET}")
|
||||
|> range(start: -24h)
|
||||
|> filter(fn: (r) => r["_measurement"] == "speedtest")
|
||||
|> filter(fn: (r) => r["_field"] == "upload_bits")
|
||||
|> tail(n: 2)
|
||||
'''
|
||||
|
||||
result_up = query_api.query(query_up)
|
||||
|
||||
up = 0
|
||||
up_prev = 0
|
||||
|
||||
upload_values = []
|
||||
|
||||
for table in result_up:
|
||||
|
||||
for record in table.records:
|
||||
|
||||
upload_values.append(
|
||||
record.get_value()
|
||||
)
|
||||
|
||||
if len(upload_values) >= 1:
|
||||
up = upload_values[-1]
|
||||
|
||||
if len(upload_values) >= 2:
|
||||
up_prev = upload_values[-2]
|
||||
|
||||
# bit/s -> Mbit/s
|
||||
|
||||
down = down / 1000 / 1000
|
||||
up = up / 1000 / 1000
|
||||
|
||||
down_prev = down_prev / 1000 / 1000
|
||||
up_prev = up_prev / 1000 / 1000
|
||||
|
||||
return down, up, down_prev, up_prev, timestamp
|
||||
|
||||
except Exception:
|
||||
|
||||
print(traceback.format_exc())
|
||||
|
||||
return 0, 0, 0, 0, "Influx Fehler"
|
||||
|
||||
# -------------------------------------------------
|
||||
# Verlaufsgrafik
|
||||
# -------------------------------------------------
|
||||
|
||||
def draw_graph(draw, values, x, y, w, h):
|
||||
|
||||
if len(values) < 2:
|
||||
return
|
||||
|
||||
max_val = max(values)
|
||||
|
||||
if max_val <= 0:
|
||||
return
|
||||
|
||||
# Dezente Hilfslinien
|
||||
|
||||
draw.line(
|
||||
(x, y + h // 2, x + w, y + h // 2),
|
||||
fill=(40, 40, 40)
|
||||
)
|
||||
|
||||
draw.line(
|
||||
(x, y + h, x + w, y + h),
|
||||
fill=(60, 60, 60)
|
||||
)
|
||||
|
||||
points = []
|
||||
|
||||
for i, val in enumerate(values):
|
||||
|
||||
px = x + int(i * (w / (len(values) - 1)))
|
||||
|
||||
py = y + h - int((val / max_val) * h)
|
||||
|
||||
points.append((px, py))
|
||||
|
||||
draw.line(points, fill="green", width=2)
|
||||
|
||||
# -------------------------------------------------
|
||||
# UI zeichnen
|
||||
# -------------------------------------------------
|
||||
|
||||
def draw_ui():
|
||||
|
||||
down, up, down_prev, up_prev, ts = get_speedtest()
|
||||
|
||||
ping = get_ping()
|
||||
|
||||
history = get_download_history()
|
||||
|
||||
img = Image.new("RGB", (WIDTH, HEIGHT), "black")
|
||||
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# Farben
|
||||
|
||||
if down < 50:
|
||||
down_color = "red"
|
||||
elif down < 90:
|
||||
down_color = "yellow"
|
||||
else:
|
||||
down_color = "green"
|
||||
|
||||
if up < 10:
|
||||
up_color = "red"
|
||||
elif up < 30:
|
||||
up_color = "yellow"
|
||||
else:
|
||||
up_color = "green"
|
||||
|
||||
if ping < 0:
|
||||
ping_color = "red"
|
||||
elif ping > 100:
|
||||
ping_color = "red"
|
||||
elif ping > 50:
|
||||
ping_color = "yellow"
|
||||
else:
|
||||
ping_color = "green"
|
||||
|
||||
# Header
|
||||
|
||||
draw.text(
|
||||
(10, 5),
|
||||
"Hintergasse 9A",
|
||||
fill="white",
|
||||
font=font_title
|
||||
)
|
||||
|
||||
draw.text(
|
||||
(10, 30),
|
||||
f"WLAN: {get_ip()}",
|
||||
fill="cyan",
|
||||
font=font_small
|
||||
)
|
||||
|
||||
draw.text(
|
||||
(240, 30),
|
||||
f"WAN: {get_wan_ip()}",
|
||||
fill="orange",
|
||||
font=font_small_bold
|
||||
)
|
||||
|
||||
if ping >= 0:
|
||||
|
||||
draw.text(
|
||||
(10, 55),
|
||||
f"PING: {ping:.1f} ms",
|
||||
fill=ping_color,
|
||||
font=font_small_bold
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
draw.text(
|
||||
(10, 55),
|
||||
"PING: FEHLER",
|
||||
fill="red",
|
||||
font=font_small_bold
|
||||
)
|
||||
|
||||
draw.line(
|
||||
(10, 80, WIDTH - 10, 80),
|
||||
fill="white"
|
||||
)
|
||||
|
||||
# DOWNLOAD
|
||||
|
||||
draw.text(
|
||||
(20, 95),
|
||||
"DOWNLOAD",
|
||||
fill="green",
|
||||
font=font_small
|
||||
)
|
||||
|
||||
draw.text(
|
||||
(20, 120),
|
||||
f"{down:.1f} Mbit/s",
|
||||
fill=down_color,
|
||||
font=font_download
|
||||
)
|
||||
|
||||
draw.text(
|
||||
(25, 172),
|
||||
f"({down_prev:.1f} Mbit/s)",
|
||||
fill=(140, 140, 140),
|
||||
font=font_delta
|
||||
)
|
||||
|
||||
# UPLOAD
|
||||
|
||||
draw.text(
|
||||
(20, 210),
|
||||
"UPLOAD",
|
||||
fill="orange",
|
||||
font=font_small
|
||||
)
|
||||
|
||||
draw.text(
|
||||
(20, 235),
|
||||
f"{up:.1f} Mbit/s",
|
||||
fill=up_color,
|
||||
font=font_upload
|
||||
)
|
||||
|
||||
draw.text(
|
||||
(25, 278),
|
||||
f"({up_prev:.1f} Mbit/s)",
|
||||
fill=(140, 140, 140),
|
||||
font=font_delta
|
||||
)
|
||||
|
||||
# Verlaufsgrafik
|
||||
|
||||
draw.text(
|
||||
(250, 190),
|
||||
"24H VERLAUF",
|
||||
fill="gray",
|
||||
font=font_small
|
||||
)
|
||||
|
||||
draw_graph(
|
||||
draw,
|
||||
history,
|
||||
250,
|
||||
215,
|
||||
200,
|
||||
80
|
||||
)
|
||||
|
||||
# Footer
|
||||
|
||||
draw.line(
|
||||
(10, HEIGHT - 20, WIDTH - 10, HEIGHT - 20),
|
||||
fill="white"
|
||||
)
|
||||
|
||||
draw.text(
|
||||
(10, HEIGHT - 18),
|
||||
f"Messung: {ts}",
|
||||
fill="gray",
|
||||
font=font_small
|
||||
)
|
||||
|
||||
return img
|
||||
|
||||
# -------------------------------------------------
|
||||
# Framebuffer schreiben
|
||||
# -------------------------------------------------
|
||||
|
||||
def write_fb(img):
|
||||
|
||||
arr = np.array(img)
|
||||
|
||||
r = (arr[:, :, 0] >> 3).astype(np.uint16)
|
||||
g = (arr[:, :, 1] >> 2).astype(np.uint16)
|
||||
b = (arr[:, :, 2] >> 3).astype(np.uint16)
|
||||
|
||||
rgb565 = (r << 11) | (g << 5) | b
|
||||
|
||||
data = rgb565.astype("<u2").tobytes()
|
||||
|
||||
with open(FB, "wb") as f:
|
||||
|
||||
f.write(data)
|
||||
|
||||
# -------------------------------------------------
|
||||
# Hauptschleife
|
||||
# -------------------------------------------------
|
||||
|
||||
while True:
|
||||
|
||||
try:
|
||||
|
||||
img = draw_ui()
|
||||
|
||||
write_fb(img)
|
||||
|
||||
except Exception:
|
||||
|
||||
print(traceback.format_exc())
|
||||
|
||||
time.sleep(60)
|
||||
Loading…
Add table
Add a link
Reference in a new issue