Internet Monitor
Shows your public IPv4 address and Internet connection status
| System | AWTRIX NG Scripts |
|---|---|
| Firmware | AWTRIX NG |
| Topic | Miscellaneous |
| Built by | Spectral |
| File | QjqyOfNgVC9w.ax · 6.6 KB |
| Icons | — |
| Published | 24 Aug 2026 |
| Downloads | 3 |
Native Internet monitor for AWTRIX NG.
Displays the current Internet status and your public IPv4 address directly on your AWTRIX display.
Features
- ONLINE / OFFLINE status
- Public IPv4 address
- Animated rainbow effect for the IP address
- Two complete IP scroll passes
- Primary IP service with automatic fallback
- Hardened offline detection to prevent false OFFLINE messages
- Configurable check and retry intervals
- Configurable scroll speed and display colors
- No API key required
- No Home Assistant, Node-RED, MQTT or ioBroker required
A single failed request does not immediately trigger OFFLINE. By default, three consecutive failed check cycles are required before the connection is considered offline.
Display sequence
MY IP → ONLINE → Public IPv4
When the Internet connection is unavailable:
MY IP → OFFLINE
Requirements
- AWTRIX NG
- Internet access
- IPv4 connectivity
Source code
https://git.mike-lindner.net/mike/awtrix-ng-internet-monitor
Version: 0.2.1
Author: Spectral
License: MIT
QjqyOfNgVC9w.ax
# @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()
Install it on your AWTRIX NG
Your browser writes the script straight to the device on your network. It joins the app rotation right away.
Some browsers refuse to talk to a device on your network from a public page. Download the flow and paste it into the Scripts tab of your device, or install it from a terminal:
More flows for AWTRIX NG Scripts or Miscellaneous
Something wrong with this flow? Report it.