Skip to content

Instantly share code, notes, and snippets.

@marco79cgn
Last active June 23, 2023 17:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marco79cgn/1f6999a9346841379458bcdc640bf7fe to your computer and use it in GitHub Desktop.
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.
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;
}
@marco79cgn
Copy link
Author

marco79cgn commented Jun 7, 2023

Intro

Das Ladepunkt Widget zeigt die Anzahl sowie den Anteil der aktuell belegten Ladepunkte in Deutschland.

Anforderungen

Installation

  • Kopiere den Source code von oben (klick)
  • Öffne die Scriptable app auf dem iPhone/iPad
  • Klick auf das "+" Symbol oben rechts und füge das kopierte Skript ein
  • Klick auf den Titel des Skripts ganz oben und vergebe einen Namen (z.B. Ladepunkte-Auslastung)
  • Speichere das Skript durch Klick auf "Done" oben links
  • Gehe auf deinen iOS Homescreen und drücke irgendwo lang, um in den "wiggle mode" zu kommen (mit dem man auch die App Symbole anordnen kann)
  • Drücke das "+" Symbol oben links, blättere dann nach unten zu "Scriptable" (Liste ist alphabetisch), wähle die erste Widget Größe (small) und drück unten auf "Widget hinzufügen"
  • Drücke auf das Widget, um seine Einstellungen zu bearbeiten (optional lang drücken, wenn der Wiggle Modus schon beendet wurde)
  • Wähle unter "Script" das oben erstellte aus (Ladepunkte-Auslastung)

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment