# @name InternetMonitor # @desc Public IPv4 and Internet status monitor # @author Spectral # @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 # @config intro_seconds number "Intro-Dauer" default=3 min=1 max=10 unit=s # @config view_seconds number "Ansichtsdauer" default=3 min=1 max=10 unit=s # @config scroll_speed number "IP Scroll-Speed" default=100 min=25 max=200 unit=% # @config online_color color "Online" default=#00FF00 # @config offline_color color "Offline" default=#FF0000 # @config info_color color "Information" default=#FFFFFF class InternetMonitor var url1, url2 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 ) 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) ) 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) ) 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 rotation.resume() rotation.next() end end end 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 ) return end # Noch kein sicherer Zustand if self.state==0 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 ) 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 ) 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 ) ) end end end end return InternetMonitor()