Indsæt scriptet
Tryk på enheden, vælg script-ikonet, og tryk Opret nyt script. Giv scriptet et navn, sæt koden nedenfor ind, og tryk Gem. Det kan også gøres fra enhedens eget webinterface.
Bruger du en computer, kan du med fordel lade editoren stå åben og åbne de næste trin i en ny browserfane.
// Elpris fra stromligning.dk — spotpris, netselskabets tariffer og afgifter
// ===== KONFIGURATION =====
let CONFIG = {
lat: "55.6736", // Breddegrad (trin 2)
long: "12.5681", // Længdegrad (trin 2)
additional_cost: 0.00, // Ekstra omkostninger fra dit elselskab, kr/kWh
// Hele URL'en kopieres fra appen og erstatter denne tekst.
// Gåseøjnene skal blive stående
post_url: "INDSÆT HELE DIN URL FRA APPEN HER",
vc_id: 0, // Id på din egen Number-komponent, fx 200. 0 = ingen
check_every_minute: false, // true henter prisen hvert minut. Kun til test — det belaster serveren, priserne hentes fra
check_delay_seconds: 10, // Sekunder efter time- eller minutskiftet, hvor prisen hentes
};
// ===== KONFIGURATION SLUT =====
let current_price = null;
let current_supplier = null;
let current_hour = 0;
// Shellys scriptmotor understøtter ikke regulære udtryk, så kolon erstattes manuelt
function encodeColon(str) {
return str.split(":").join("%3A");
}
function pad2(n) {
return ("0" + n).slice(-2);
}
// Afgjort på formen frem for på en bestemt tekst: en adresse, scriptet kan
// sende til, begynder med https://. Det fanger både pladsholderen, et tomt
// felt og en halvfærdig indtastning, så en uopsat enhed ikke forsøger en
// forgæves POST i timen
function postUrlIsSet() {
return CONFIG.post_url.indexOf("https://") === 0;
}
// Slår afsendelsen fejl, skal resten af scriptet køre videre uanset hvad:
// prisen er hentet, og kun visningen i appen mangler
function postResult(res, code, msg) {
if (code !== 0) {
print("Kunne ikke sende prisen til appen — tjek post_url");
} else {
print("Pris sendt til appen: " + current_price);
}
}
function handlePrice(price) {
current_price = price;
print("Elpris nu: " + price + " kr/kWh");
if (CONFIG.vc_id) {
// Number.Set kræver et tal. Sender man teksten fra toFixed(2), bliver
// komponenten aldrig opdateret — lav det ikke om til tekst igen
Shelly.call("Number.Set", { id: CONFIG.vc_id, value: price });
}
if (postUrlIsSet()) {
// Appen har modtaget prisen som tekst med to decimaler siden 2025.
// Her skal den altså være tekst — modsat Number.Set ovenfor
Shelly.call("HTTP.Request", {
method: "POST",
url: CONFIG.post_url,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ price: price.toFixed(2) }),
timeout: 5,
}, postResult);
} else {
// Ikke en fejl. At lade være med at vise prisen i appen er en gyldig opsætning
print("Prisen sendes ikke til appen — post_url er ikke udfyldt.");
}
}
function onPrices(res, code, msg) {
if (code !== 0) {
print("Fejl ved hentning af pris: " + msg);
scheduleNextCheck();
return;
}
let data = JSON.parse(res.body);
if (!data.prices || data.prices.length === 0) {
print("Ingen prisdata modtaget.");
scheduleNextCheck();
return;
}
let found = false;
for (let i = 0; i < data.prices.length; i++) {
let item = data.prices[i];
if (new Date(item.date).getHours() === current_hour) {
found = true;
let total = item.price.total + CONFIG.additional_cost;
handlePrice(Math.floor(total * 100 + 0.5) / 100);
}
}
if (!found) {
print("Ingen pris fundet for timen " + current_hour + ":00.");
}
scheduleNextCheck();
}
function onSupplier(res, code, msg) {
if (code !== 0) {
print("Fejl ved opslag af netselskab: " + msg);
scheduleNextCheck();
return;
}
let suppliers = JSON.parse(res.body);
if (!suppliers || suppliers.length === 0) {
print("Intet netselskab fundet for de angivne koordinater.");
scheduleNextCheck();
return;
}
current_supplier = suppliers[0];
print("Netselskab: " + current_supplier.id + " — prisomraade: " + current_supplier.priceArea);
let now = new Date();
current_hour = now.getHours();
let stamp = now.getFullYear() + "-" + pad2(now.getMonth() + 1) + "-" + pad2(now.getDate()) + "T" + pad2(current_hour);
let from = encodeColon(stamp + ":00:00");
let to = encodeColon(stamp + ":45:00");
let priceUrl = "https://stromligning.dk/api/prices?from=" + from + "&to=" + to +
"&supplierId=" + current_supplier.id + "&aggregation=1h&priceArea=" + current_supplier.priceArea;
Shelly.call("HTTP.GET", { url: priceUrl }, onPrices);
}
function getCurrentPrice() {
let supplierUrl = "https://stromligning.dk/api/suppliers/find?lat=" + CONFIG.lat + "&long=" + CONFIG.long;
Shelly.call("HTTP.GET", { url: supplierUrl }, onSupplier);
}
function scheduleNextCheck() {
let now = new Date();
let delay;
if (CONFIG.check_every_minute) {
let msIntoMinute = now.getSeconds() * 1000;
delay = (60 * 1000) - msIntoMinute + (CONFIG.check_delay_seconds * 1000);
} else {
let msIntoHour = (now.getMinutes() * 60 + now.getSeconds()) * 1000;
delay = (3600 * 1000) - msIntoHour + (CONFIG.check_delay_seconds * 1000);
}
print("Naeste prischeck om " + Math.floor(delay / 1000) + " sekunder");
Timer.set(delay, false, getCurrentPrice);
}
getCurrentPrice();






