Nochmal bischen optimiert (z für Zulu) und die Abrufzeit mit eingeblendet, BDE in ECET umbenannt. War kürzlich schon ganz praktisch auch im Anflug die aktive Piste übers Internet schnell mal abzurufen und schon 15min vorher Klarheit zu haben. Habe im Übrigen mal den DWD gebeten die MET-Reports zu veröffentlichen oder zumindest in der Flugwetter-APP verfügbar zu machen, wobei die nicht für schlechten Empfang optimiert ist und mich meist genau dort ausloggt.
// ----------------------------------------------------
// URLs
// ----------------------------------------------------
let urlMetar = "https://images.egelsbach-airport.com/METREPEgelsbach/metrep.jpg"
let urlCam = "https://images.egelsbach-airport.com/WebCamEgelsbach/Wetter.jpg"
let urlDWD = "https://www.dwd.de/DE/fachnutzer/luftfahrt/teaser/luftsportberichte/edfe/node.html"
// ----------------------------------------------------
// EINSTELLUNGEN
// ----------------------------------------------------
let cropWidget = 30
let cropFullscreen = 80
let safeAreaMargin = 00
// ----------------------------------------------------
// ----------------------------------------------------
// LOGIK
// ----------------------------------------------------
let isFullscreen = (args.queryParameters["fullscreen"] === "true")
let showWidget = config.runsInWidget || !isFullscreen
let activeCrop = showWidget ? cropWidget : cropFullscreen
let activeMargin = showWidget ? safeAreaMargin : 0
// ----------------------------------------------------
// WIDGET-GRÖSSE (IN PUNKTEN!)
// ----------------------------------------------------
let widgetWidthPt = 329
let widgetHeightPt = 155
let canvasW = widgetWidthPt
let canvasH = widgetHeightPt
// ----------------------------------------------------
// DATEN LADEN (Bilder & DWD ECET)
// ----------------------------------------------------
let reqMetar = new Request(urlMetar + "?t=" + Date.now())
let imgMetar = await reqMetar.loadImage()
let reqCam = new Request(urlCam + "?t=" + Date.now())
let imgCam = await reqCam.loadImage()
async function fetchECET() {
try {
let req = new Request(urlDWD)
let html = await req.loadString()
let now = new Date()
let year = now.getFullYear()
let month = ("0" + (now.getMonth() + 1)).slice(-2)
let day = ("0" + now.getDate()).slice(-2)
let todayStr = year + "-" + month + "-" + day
let rows = html.split("\n")
for (let row of rows) {
if (row.includes(todayStr)) {
let cleanRow = row.replace(/<[^>]*>/g, " ").trim()
let parts = cleanRow.split(/\s+/).filter(p => p.length > 0)
// Index 5 ist die Zeit für ECET.
if (parts.length >= 6) {
return parts[5]
}
}
}
return "--"
} catch(e) {
return "Err"
}
}
let ecetTime = await fetchECET()
// ----------------------------------------------------
// DRAW CONTEXT
// ----------------------------------------------------
let ctx = new DrawContext()
ctx.size = new Size(canvasW, canvasH)
ctx.respectScreenScale = true
ctx.opaque = true
// ----------------------------------------------------
// 1. Webcam Hintergrund
// ----------------------------------------------------
let camW = imgCam.size.width
let camH = imgCam.size.height
let scaleCam = Math.max(canvasW / camW, canvasH / camH)
let drawCamW = camW * scaleCam
let drawCamH = camH * scaleCam
let drawCamX = (canvasW - drawCamW) / 2
let drawCamY = (canvasH - drawCamH) / 2
ctx.drawImageInRect(imgCam, new Rect(drawCamX, drawCamY, drawCamW, drawCamH))
// ----------------------------------------------------
// 2. METAR Overlay
// ----------------------------------------------------
let metarW = imgMetar.size.width
let metarH = imgMetar.size.height
let scaleMetar = canvasH / metarH
let drawMetW = metarW * scaleMetar
let drawMetH = canvasH
let shiftLeft = activeCrop * scaleMetar
let drawMetX = -shiftLeft + activeMargin
let drawMetY = 0
ctx.drawImageInRect(imgMetar, new Rect(drawMetX, drawMetY, drawMetW, drawMetH))
// ----------------------------------------------------
// 3. ECET Text & UTC Einblendung (Rechtsbündig unten)
// ----------------------------------------------------
if (ecetTime) {
// Aktuelle UTC Zeit generieren
let timeNow = new Date()
let utcH = ("0" + timeNow.getUTCHours()).slice(-2)
let utcM = ("0" + timeNow.getUTCMinutes()).slice(-2)
let utcTime = utcH + ":" + utcM
// Zwei getrennte Textblöcke für perfekte Ausrichtung
let labelText = "ECET:\nFROM:"
let valueText = ecetTime + "ᶻ\n" + utcTime + "ᶻ"
// Angepasste Box-Größe (100px breit, 30px hoch)
let bgW = 72
let bgH = 30
// Box liegt wieder bündig rechts am Rand
let bgX = canvasW - bgW
let bgY = canvasH - bgH
// Halbtransparenter Hintergrundkasten
let bgRect = new Rect(bgX, bgY, bgW, bgH)
ctx.setFillColor(new Color("000000", 0.4))
ctx.fillRect(bgRect)
// Globale Texteinstellungen
ctx.setFont(Font.boldSystemFont(9))
ctx.setTextColor(Color.white())
// 1. Spalte: Labels (Linksbündig zeichnen) - Textfeld startet um 2 Pixel weiter links als vorher (jetzt bgX + 4 statt bgX + 6)
ctx.setTextAlignedLeft()
let rectLabels = new Rect(bgX + 1, bgY + 3, bgW - 10, bgH)
ctx.drawTextInRect(labelText, rectLabels)
// 2. Spalte: Zeiten (Rechtsbündig zeichnen) - Rechte Kante rückt um genau 2 Pixel nach links
ctx.setTextAlignedRight()
let rectValues = new Rect(bgX + 1, bgY + 3, bgW - 10, bgH)
ctx.drawTextInRect(valueText, rectValues)
}
let compositeImg = ctx.getImage()
// ----------------------------------------------------
// AUSGABE
// ----------------------------------------------------
if (showWidget) {
let widget = new ListWidget()
widget.url =
"scriptable:///run?scriptName=" +
encodeURIComponent(Script.name()) +
"&fullscreen=true"
widget.backgroundImage = compositeImg
widget.refreshAfterDate = new Date(Date.now() + 5 * 60 * 1000)
if (config.runsInWidget) {
Script.setWidget(widget)
} else {
await widget.presentMedium()
}
Script.complete()
} else {
let view = new WebView()
let imgData = Data.fromPNG(compositeImg).toBase64String()
let base64Url = "data:image/png;base64," + imgData
let html = `
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
margin:0;
background:black;
display:flex;
justify-content:center;
align-items:center;
min-height:100vh;
}
img {
width:100%;
height:auto;
}
</style>
</head>
<body>
<img src="${base64Url}">
</body>
</html>
`
await view.loadHTML(html)
await view.present(true)
Script.complete()
}