Last active
September 26, 2024 18:56
-
-
Save marco79cgn/1f6999a9346841379458bcdc640bf7fe to your computer and use it in GitHub Desktop.
iOS widget, das die Anzahl sowie den Anteil der aktuell belegten Ladepunkte in Deutschland zeigt.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const canvSize = 200; | |
const canvTextSize = 80; | |
const canvas = new DrawContext(); | |
canvas.opaque = false; | |
const battCircleRemainColor = new Color("#32CD33"); // Charge circle remaining color | |
const battCircleDepletedColor = new Color("#fff"); | |
const battCircleBGColor = new Color('#fff'); // Widget background color | |
const battCircleTextColor = new Color('#000'); // Widget text color | |
const labelColor = new Color('#768178') | |
const textColor = new Color('#34443c') | |
const canvWidth = 16; // Charge circle thickness | |
const canvRadius = 80; // Charge circle radius | |
canvas.size = new Size(canvSize, canvSize); | |
canvas.respectScreenScale = true; | |
let widget = await createWidget() | |
Script.setWidget(widget) | |
Script.complete() | |
widget.presentSmall() | |
async function createWidget() { | |
let widget = new ListWidget() | |
widget.setPadding(10, 10, 8, 8) | |
widget.url = "https://nationale-leitstelle.de/verstehen/" | |
widget.backgroundColor = new Color("#1e2040") | |
let apiData = await getApiData() | |
const batteryLevel = apiData.percent; | |
let chargeStack = widget.addStack() | |
let chargeIcon = await getImage("charger.png") | |
drawArc( | |
Math.floor(batteryLevel * 3.6), | |
battCircleRemainColor, | |
battCircleDepletedColor, | |
battCircleTextColor, | |
chargeIcon | |
) | |
chargeStack.addImage(canvas.getImage()) | |
chargeStack.addSpacer(6) | |
let infoStack = chargeStack.addStack() | |
infoStack.layoutVertically() | |
infoStack.addSpacer(32) | |
let percentageText = infoStack.addText(batteryLevel.toString().replace(".", ",") + "%") | |
percentageText.font = Font.mediumSystemFont(20) | |
percentageText.textColor = new Color("#30cd33") | |
widget.addSpacer(4) | |
let chargingPoint = widget.addText("BELEGTE LADEPUNKTE") | |
chargingPoint.font = Font.boldSystemFont(11) | |
chargingPoint.textColor = Color.white() | |
chargingPoint.textOpacity = 0.8 | |
let chargingPointNo = widget.addText(Math.round(apiData.current).toLocaleString()) | |
chargingPointNo.font = Font.boldSystemFont(12) | |
chargingPointNo.textColor = Color.white() | |
widget.addSpacer() | |
const lastUpdateDate = new Date().toLocaleTimeString("de-DE", { | |
timeZone: "CET", | |
hour: '2-digit', | |
minute: '2-digit' | |
}) | |
let lastUpdatedText = widget.addText("Stand: " + lastUpdateDate + " Uhr") | |
lastUpdatedText.textColor = Color.white() | |
lastUpdatedText.font = Font.mediumSystemFont(9) | |
lastUpdatedText.centerAlignText() | |
return widget | |
} | |
// get images from local filestore or download them once | |
async function getImage(image) { | |
let fm = FileManager.local() | |
let dir = fm.documentsDirectory() | |
let path = fm.joinPath(dir, image) | |
if (fm.fileExists(path)) { | |
return fm.readImage(path) | |
} else { | |
// download once | |
let imageUrl | |
switch (image) { | |
case 'charger.png': | |
imageUrl = "https://i.imgur.com/nBuZv5M.png" | |
break | |
case 'leitstelle-logo.png': | |
imageUrl = "https://i.imgur.com/cXcq1t3.png" | |
break | |
default: | |
console.log(`Sorry, couldn't find ${image}.`); | |
} | |
let iconImage = await loadImage(imageUrl) | |
fm.writeImage(path, iconImage) | |
return iconImage | |
} | |
} | |
// helper function to download an image from a given url | |
async function loadImage(imgUrl) { | |
const req = new Request(imgUrl) | |
return await req.loadImage() | |
} | |
// query api data | |
async function getApiData() { | |
let apiUrl = "https://c1022.api.cit-fusion.com/ticker" | |
const req = new Request(apiUrl) | |
let apiResult = await req.loadString() | |
let result | |
// check if call has been successful | |
if (req.response.statusCode == 200) { | |
// console.log("Successfully retrieved bike data!") | |
const numbers = apiResult.split(";") | |
const total = numbers[0] | |
const current = numbers[1] | |
const previous = numbers[2] | |
const percent = 100 / total * current | |
const percentRounded = round(percent, 1).toFixed(1) | |
result = { | |
"current": current, | |
"previous": previous, | |
"percent": percentRounded | |
} | |
} | |
return result | |
} | |
function sinDeg(deg) { | |
return Math.sin((deg * Math.PI) / 180); | |
} | |
function cosDeg(deg) { | |
return Math.cos((deg * Math.PI) / 180); | |
} | |
// draw charging circle | |
function drawArc(deg, fillColor, strokeColor, txtColor, chargeIcon) { | |
let ctr = new Point(canvSize / 2, canvSize / 2), | |
bgx = ctr.x - canvRadius; | |
bgy = ctr.y - canvRadius; | |
bgd = 2 * canvRadius; | |
bgr = new Rect(bgx, bgy, bgd, bgd); | |
// canvas.opaque = false; | |
canvas.setFillColor(fillColor); | |
canvas.setStrokeColor(strokeColor); | |
canvas.setLineWidth(canvWidth); | |
canvas.strokeEllipse(bgr); | |
for (t = 0; t < deg; t++) { | |
rect_x = ctr.x + canvRadius * sinDeg(t) - canvWidth / 2; | |
rect_y = ctr.y - canvRadius * cosDeg(t) - canvWidth / 2; | |
rect_r = new Rect(rect_x, rect_y, canvWidth, canvWidth); | |
canvas.fillEllipse(rect_r); | |
} | |
// attempt to draw info text | |
const canvTextRect = new Rect( | |
0, | |
(100 - canvTextSize / 2), | |
canvSize, | |
canvTextSize | |
); | |
const canvLabelRect = new Rect( | |
58, | |
(100 - canvTextSize / 2) - 6, | |
90, | |
90 | |
); | |
canvas.setTextAlignedCenter(); | |
canvas.setTextColor(txtColor); | |
canvas.setFont(Font.boldSystemFont(canvTextSize)); | |
canvas. | |
drawImageInRect(chargeIcon, canvLabelRect) | |
} | |
function round(value, precision) { | |
var multiplier = Math.pow(10, precision || 0); | |
return Math.round(value * multiplier) / multiplier; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Intro
Das Ladepunkt Widget zeigt die Anzahl sowie den Anteil der aktuell belegten Ladepunkte in Deutschland.
Anforderungen
Installation
Disclaimer
Es handelt sich um ein von mir selbst entwickeltes Spaßprojekt, kein offizielles Produkt der Nationale Leitstelle Ladeinfrastruktur.
Kostenloses Ladestation-Icon designt von berkahicon via @flaticon
Updates
23.06.2023, 19:46
removed logo
added dark mode
07.06.2023, 23:06
Erste Version