Release v0.2.1

This commit is contained in:
2026-08-22 15:14:11 +02:00
parent d6a4b4c27e
commit 39e8a74ed6
3 changed files with 159 additions and 11 deletions
+150 -10
View File
@@ -1,7 +1,8 @@
# @name InternetMonitor
# @desc Public IPv4 and Internet status monitor
# @author Spectral
# @version 0.2.0
# @version 0.2.1
# @url https://git.mike-lindner.net/mike/awtrix-ng-internet-monitor
# @config refresh number "Prüfintervall" default=60 min=30 max=1800 unit=s
# @config retry_seconds number "Fehler-Retry" default=15 min=5 max=60 unit=s
# @config fail_threshold number "Offline nach Fehlern" default=3 min=1 max=10
@@ -17,105 +18,182 @@ class InternetMonitor
var refreshms, retryms, threshold
var introms, viewms
var speed, onlinec, offlinec, infoc
var state, flight, attempt, fails
var nextcheck
var ip, ipw
var xintro, xon, xoff, xcheck
var phase, phaseat
var scrollat, scrollms
def init()
self.url1="https://api.ipify.org"
self.url2="https://checkip.global.api.aws/"
self.refreshms=store.get("refresh")*1000
self.retryms=store.get("retry_seconds")*1000
self.threshold=store.get("fail_threshold")
self.introms=store.get("intro_seconds")*1000
self.viewms=store.get("view_seconds")*1000
self.speed=store.get("scroll_speed")
self.onlinec=store.get("online_color")
self.offlinec=store.get("offline_color")
self.infoc=store.get("info_color")
# state:
# 0 = noch kein sicherer Zustand
# 1 = online
# -1 = offline
self.state=0
self.flight=false
self.attempt=0
self.fails=0
# Sofort nach dem Start prüfen
self.nextcheck=0
# Letzte bekannte öffentliche IPv4 übernehmen
self.ip=store.get("ip")
if self.ip==nil
self.ip="---.---.---.---"
end
self.ipw=text_width(self.ip)
# Textpositionen vorberechnen
self.xintro=(width()-text_ink_width("MY IP"))/2
self.xon=7+(width()-7-text_ink_width("ONLINE"))/2
self.xoff=7+(width()-7-text_ink_width("OFFLINE"))/2
self.xcheck=(width()-text_ink_width("CHECK"))/2
# Phasen:
# 0 = normale Rotation
# 1 = MY IP
# 2 = ONLINE / OFFLINE / CHECK
# 3 = Rainbow-IP
self.phase=0
self.phaseat=0
self.scrollat=0
self.scrollms=0
end
def on_body(b,st)
var m=nil
# Diese Version verarbeitet bewusst nur IPv4.
if b!=nil && st>=200 && st<300
m=re.search("([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)",b)
m=re.search(
"([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)",
b
)
end
# Primärer Dienst fehlgeschlagen:
# AWS einmal als Fallback versuchen
if m==nil
if self.attempt==0
self.attempt=1
http.get(self.url2,/ b,s -> self.on_body(b,s))
http.get(
self.url2,
/ b,s -> self.on_body(b,s)
)
return
end
# Beide Dienste in diesem Prüfzyklus fehlgeschlagen
self.flight=false
self.fails+=1
# Nach Fehler schneller erneut prüfen
self.nextcheck=now_ms()+self.retryms
# Erst nach mehreren aufeinanderfolgenden
# Fehlerzyklen wirklich OFFLINE melden
if self.fails>=self.threshold
self.state=-1
store.set("online",false)
end
return
end
# Erfolgreiche Antwort
self.flight=false
self.fails=0
self.state=1
self.ip=m[1]
self.ipw=text_width(self.ip)
# Wieder normales Prüfintervall verwenden
self.nextcheck=now_ms()+self.refreshms
store.set("ip",self.ip)
store.set("online",true)
end
def loop()
var n=now_ms()
# Internet/Public-IPv4 prüfen
if !self.flight && n>=self.nextcheck
self.flight=true
self.attempt=0
# Mehrfachen Request-Start verhindern
self.nextcheck=n+self.refreshms
http.get(self.url1,/ b,s -> self.on_body(b,s))
http.get(
self.url1,
/ b,s -> self.on_body(b,s)
)
end
# MY IP Intro
if self.phase==1
if n-self.phaseat>=self.introms
self.phase=2
self.phaseat=n
end
# ONLINE / OFFLINE / CHECK
elif self.phase==2
if n-self.phaseat>=self.viewms
if self.state==1
self.phase=3
self.scrollat=n
# 100 % entsprechen ungefähr 21 Pixel/s
var pxps=21*self.speed/100
if pxps<1
pxps=1
end
# Strecke eines vollständigen Durchlaufs
var run=width()+self.ipw
# Zwei vollständige IP-Durchläufe
self.scrollms=int(run*1000/pxps)*2
else
self.phase=0
rotation.resume()
rotation.next()
end
end
# Rainbow-IP nach zwei Durchläufen beenden
elif self.phase==3
if n-self.scrollat>=self.scrollms
self.phase=0
@@ -128,48 +206,110 @@ class InternetMonitor
def on_show()
self.phase=1
self.phaseat=now_ms()
# Eigene Sequenz vollständig anzeigen
rotation.pause()
end
def draw()
clear()
# Intro
if self.phase==1
text(self.xintro,6,"MY IP",self.infoc)
text(
self.xintro,
6,
"MY IP",
self.infoc
)
return
end
# Noch kein sicherer Zustand
if self.state==0
text(self.xcheck,6,"CHECK",self.infoc)
text(
self.xcheck,
6,
"CHECK",
self.infoc
)
return
end
# Offline erst nach bestätigten Fehlerzyklen
if self.state<0
line(1,2,5,6,self.offlinec)
line(1,6,5,2,self.offlinec)
text(self.xoff,6,"OFFLINE",self.offlinec)
text(
self.xoff,
6,
"OFFLINE",
self.offlinec
)
return
end
# Online
if self.phase==2
line(1,4,2,5,self.onlinec)
line(2,5,5,2,self.onlinec)
text(self.xon,6,"ONLINE",self.onlinec)
text(
self.xon,
6,
"ONLINE",
self.onlinec
)
return
end
# Animierte Rainbow-IP
if self.phase==3
var n=now_ms()
# Wichtig: gleiche Berechnung wie in loop()
var pxps=21*self.speed/100
if pxps<1
pxps=1
end
# Länge eines vollständigen Durchlaufs
var run=width()+self.ipw
# Dauer eines Durchlaufs
var runms=int(run*1000/pxps)
# Zeit innerhalb des aktuellen Durchlaufs.
# Beim zweiten Durchlauf wieder bei 0 beginnen.
var elapsed=(n-self.scrollat)%runms
# Scrollposition
var px=int(elapsed*pxps/1000)
var x=width()-px
# Animierter HSV-Regenbogen.
# Beide Durchläufe starten mit derselben Farbphase.
var ph=int(elapsed/20)%360
for i : 0 .. size(self.ip)-1
x+=text(x,6,self.ip[i],hsv((ph+i*30)%360,100,100))
x+=text(
x,
6,
self.ip[i],
hsv(
(ph+i*30)%360,
100,
100
)
)
end
end
end
end
return InternetMonitor()
return InternetMonitor()