Initial release v0.2.0
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.tmp
|
||||||
|
*.swp
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [0.2.0]
|
||||||
|
### Added
|
||||||
|
- `MY IP` intro
|
||||||
|
- Animated HSV rainbow effect
|
||||||
|
- Two complete IP scroll passes
|
||||||
|
- Configurable scroll speed
|
||||||
|
- Configurable retry interval
|
||||||
|
- Configurable offline failure threshold
|
||||||
|
- Secondary public IP service as fallback
|
||||||
|
- Hardened ONLINE/OFFLINE detection
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- A single failed request no longer causes OFFLINE
|
||||||
|
- Failed checks use a shorter retry interval
|
||||||
|
- Successful checks immediately reset the failure counter
|
||||||
|
- Public IP uses an animated per-character rainbow effect
|
||||||
|
|
||||||
|
## [0.1.0]
|
||||||
|
### Added
|
||||||
|
- Initial Internet connectivity monitoring
|
||||||
|
- Public IPv4 detection
|
||||||
|
- ONLINE/OFFLINE display
|
||||||
|
- Configurable refresh interval
|
||||||
|
- Configurable display colors
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
# @name InternetMonitor
|
||||||
|
# @desc Public IPv4 and Internet status monitor
|
||||||
|
# @author Spectral
|
||||||
|
# @version 0.2.0
|
||||||
|
# @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")
|
||||||
|
self.state=0
|
||||||
|
self.flight=false
|
||||||
|
self.attempt=0
|
||||||
|
self.fails=0
|
||||||
|
self.nextcheck=0
|
||||||
|
self.ip=store.get("ip")
|
||||||
|
if self.ip==nil
|
||||||
|
self.ip="---.---.---.---"
|
||||||
|
end
|
||||||
|
self.ipw=text_width(self.ip)
|
||||||
|
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
|
||||||
|
self.phase=0
|
||||||
|
self.phaseat=0
|
||||||
|
self.scrollat=0
|
||||||
|
self.scrollms=0
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_body(b,st)
|
||||||
|
var m=nil
|
||||||
|
if b!=nil && st>=200 && st<300
|
||||||
|
m=re.search("([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)",b)
|
||||||
|
end
|
||||||
|
if m==nil
|
||||||
|
if self.attempt==0
|
||||||
|
self.attempt=1
|
||||||
|
http.get(self.url2,/ b,s -> self.on_body(b,s))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.flight=false
|
||||||
|
self.fails+=1
|
||||||
|
self.nextcheck=now_ms()+self.retryms
|
||||||
|
if self.fails>=self.threshold
|
||||||
|
self.state=-1
|
||||||
|
store.set("online",false)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.flight=false
|
||||||
|
self.fails=0
|
||||||
|
self.state=1
|
||||||
|
self.ip=m[1]
|
||||||
|
self.ipw=text_width(self.ip)
|
||||||
|
self.nextcheck=now_ms()+self.refreshms
|
||||||
|
store.set("ip",self.ip)
|
||||||
|
store.set("online",true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def loop()
|
||||||
|
var n=now_ms()
|
||||||
|
if !self.flight && n>=self.nextcheck
|
||||||
|
self.flight=true
|
||||||
|
self.attempt=0
|
||||||
|
self.nextcheck=n+self.refreshms
|
||||||
|
http.get(self.url1,/ b,s -> self.on_body(b,s))
|
||||||
|
end
|
||||||
|
if self.phase==1
|
||||||
|
if n-self.phaseat>=self.introms
|
||||||
|
self.phase=2
|
||||||
|
self.phaseat=n
|
||||||
|
end
|
||||||
|
elif self.phase==2
|
||||||
|
if n-self.phaseat>=self.viewms
|
||||||
|
if self.state==1
|
||||||
|
self.phase=3
|
||||||
|
self.scrollat=n
|
||||||
|
var pxps=21*self.speed/100
|
||||||
|
if pxps<1
|
||||||
|
pxps=1
|
||||||
|
end
|
||||||
|
var run=width()+self.ipw
|
||||||
|
self.scrollms=int(run*1000/pxps)*2
|
||||||
|
else
|
||||||
|
self.phase=0
|
||||||
|
rotation.resume()
|
||||||
|
rotation.next()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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()
|
||||||
|
rotation.pause()
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw()
|
||||||
|
clear()
|
||||||
|
if self.phase==1
|
||||||
|
text(self.xintro,6,"MY IP",self.infoc)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.state==0
|
||||||
|
text(self.xcheck,6,"CHECK",self.infoc)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
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
|
||||||
|
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
|
||||||
|
if self.phase==3
|
||||||
|
var n=now_ms()
|
||||||
|
var pxps=21*self.speed/100
|
||||||
|
if pxps<1
|
||||||
|
pxps=1
|
||||||
|
end
|
||||||
|
var run=width()+self.ipw
|
||||||
|
var runms=int(run*1000/pxps)
|
||||||
|
var elapsed=(n-self.scrollat)%runms
|
||||||
|
var px=int(elapsed*pxps/1000)
|
||||||
|
var x=width()-px
|
||||||
|
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()
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Spectral
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
# AWTRIX NG Internet Monitor
|
||||||
|
|
||||||
|
Native AWTRIX NG script that monitors Internet connectivity and displays the current public IPv4 address directly on the device.
|
||||||
|
|
||||||
|
No Home Assistant, Node-RED, MQTT, ioBroker or API key is required.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- Public IPv4 display
|
||||||
|
- ONLINE / OFFLINE status
|
||||||
|
- Animated HSV rainbow effect for the public IP
|
||||||
|
- Two complete IP scroll passes
|
||||||
|
- Primary IP service plus AWS fallback
|
||||||
|
- Hardened offline detection
|
||||||
|
- Faster retry interval after failed checks
|
||||||
|
- Last known public IPv4 stored locally
|
||||||
|
- Configurable timings, scroll speed and colors
|
||||||
|
- No API key required
|
||||||
|
|
||||||
|
## Display sequence
|
||||||
|
|
||||||
|
Online:
|
||||||
|
|
||||||
|
```text
|
||||||
|
MY IP
|
||||||
|
↓
|
||||||
|
✓ ONLINE
|
||||||
|
↓
|
||||||
|
Public IPv4 with animated rainbow effect
|
||||||
|
(two complete scroll passes)
|
||||||
|
```
|
||||||
|
|
||||||
|
Offline:
|
||||||
|
|
||||||
|
```text
|
||||||
|
MY IP
|
||||||
|
↓
|
||||||
|
✕ OFFLINE
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reliability
|
||||||
|
A single failed HTTP request does not immediately mean the Internet connection is offline. Each failed check cycle tries both services. By default, three consecutive failed cycles are required before `OFFLINE` is shown. After a failed cycle, the script retries after 15 seconds. Any successful check immediately resets the failure counter.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
| Setting | Default | Description |
|
||||||
|
|---|---:|---|
|
||||||
|
| `refresh` | 60 s | Normal check interval |
|
||||||
|
| `retry_seconds` | 15 s | Retry interval after a failed cycle |
|
||||||
|
| `fail_threshold` | 3 | Failed cycles required before OFFLINE |
|
||||||
|
| `intro_seconds` | 3 s | Duration of `MY IP` |
|
||||||
|
| `view_seconds` | 3 s | Duration of ONLINE/OFFLINE |
|
||||||
|
| `scroll_speed` | 100 % | Public IP scroll speed |
|
||||||
|
| `online_color` | `#00FF00` | ONLINE color |
|
||||||
|
| `offline_color` | `#FF0000` | OFFLINE color |
|
||||||
|
| `info_color` | `#FFFFFF` | Neutral information color |
|
||||||
|
|
||||||
|
## Public IP services
|
||||||
|
1. `https://api.ipify.org`
|
||||||
|
2. `https://checkip.global.api.aws/` as fallback
|
||||||
|
|
||||||
|
## Privacy
|
||||||
|
The external IP-check services necessarily receive the public source IP address of the request. The script does not intentionally transmit additional personal data.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
- AWTRIX NG
|
||||||
|
- Internet access from the device
|
||||||
|
- IPv4 connectivity
|
||||||
|
|
||||||
|
## IPv6
|
||||||
|
Version 0.2.0 supports public IPv4 only.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
1. Open the AWTRIX NG web interface.
|
||||||
|
2. Go to **Scripts**.
|
||||||
|
3. Create a script named `InternetMonitor`.
|
||||||
|
4. Paste `InternetMonitor.ax`.
|
||||||
|
5. Save it.
|
||||||
|
6. Configure it under **Apps → InternetMonitor → Settings** if required.
|
||||||
|
|
||||||
|
## Version
|
||||||
|
**0.2.0**
|
||||||
|
|
||||||
|
## Author
|
||||||
|
Spectral
|
||||||
|
|
||||||
|
## License
|
||||||
|
MIT
|
||||||
Reference in New Issue
Block a user