jul 13, 2025 In Shelly, Smarthome Tag Shelly, Shelly Dimmer, Strømmåling Ved at køre et script på en shelly enhed kan vi få live elpriser direkte i appen. Så får du nemt et overblik over de præcise omkostninger for dit forbrug. Hvad skal der bruges Du skal bruge en shelly enhed, der understøtter scripting (Gen2 eller nyere) Du skal have mindst en enhed der måler effekt (PM eller EM) Brug shelly smart control appen eller http://control.shelly.cloud på din pc, det anbefales og det er også det jeg benytter i denne guide. Hvis man vil bruge funktionen Virtuelle enheder, så kræves det som minimum en Gen3 eller pro enheder og nyere. Kopier nedenstående script 1Som henter døgnets elpriser fra strømligning.dk ud fra længde og bredegrad. (Henter ved døgnskift)Gemmer priser i KVS (Key Value Storage) Husk at rette Længde og breddegrad. // Henter data fra https://stromligning.dk //===== KONFIGURATION ===== let CONFIG = { // Indtast breddegrad og længdegrad lat: "55.3555", // Indtast breddegrad long: "9.483427", // Indtast længdegrad additionalCost: 0.00, // Yderligere omkostninger (kr/kWh), som lægges oven i price.total post_url: "https://shelly-116-eu.shelly.cloud/v2/users/pp-ltu/eyJpZCI6MTIwNjk2OSwic24iOjczNDM3Mjk2MzJ9.iQqz0Pc3umU9t18FMXTncKOTSg6ftQSGIN5e4zTNmnA", // (Valgfrit) URL til POST – fjern eller tilpas, hvis ikke relevant vc_id: 200, // (Valgfrit) ID på den virtuelle enhed, hvis prisen skal vises i Shelly GUI // Styring af opdaterings-frekvens // For ikke at belaste server, hvor prisen hentes bør den være sat til false. 1 minut check bør kun bruges til at teste om det virker. check_every_minute: false, // true = tjek prisen hvert minut, false = tjek prisen hver time check_delay_seconds: 10, // Antal sekunder efter time-/minutskiftet, hvorefter prischecket udføres }; //===== KONFIGURATION SLUT===== let current_price = null; // Her gemmes den aktuelle pris (til reference) let loggingIntervalTimer = null; // ID på gentaget log-timer (bruges til nedtælling) let nextUpdateInMs = 0; // Tid til næste update (i ms) // Hjælpefunktion: Formaterer millisekunder til "0h 5m 10s" function formatDelay(delayMs) { let totalSeconds = Math.floor(delayMs / 1000); let hours = Math.floor(totalSeconds / 3600); let minutes = Math.floor((totalSeconds % 3600) / 60); let seconds = totalSeconds % 60; return hours + "h " + minutes + "m " + seconds + "s"; } // Enkel URL-encoding: erstatter kolon (:) med "%3A" // (Espruino understøtter ikke regulære udtryk i denne version) function myEncodeURIComponent(str) { return str.split(":").join("%3A"); } /** * Henter den aktuelle pris ved først at slå supplier op (ud fra bredde- og længdegrad) * og derefter hente prisdata for den aktuelle time. * Resultatet (price.total + additionalCost) vises og sendes evt. videre. */ function getCurrentPrice() { // 1. HENT SUPPLIER-DATA let supplierUrl = "https://stromligning.dk/api/suppliers/find?lat=" + CONFIG.lat + "&long=" + CONFIG.long; print("Henter supplier-data fra: " + supplierUrl); Shelly.call("HTTP.GET", { url: supplierUrl }, function(supplierResult, supplierErrorCode, supplierErrorMessage) { if (supplierErrorCode !== 0) { print("Fejl ved supplier API GET: " + supplierErrorMessage); scheduleNextPriceCheck(); return; } let suppliers = JSON.parse(supplierResult.body); if (!suppliers || suppliers.length === 0) { print("Ingen supplier-data modtaget."); scheduleNextPriceCheck(); return; } // Da vi kun forventer ét netselskab, benyt det direkte let supplier = suppliers[0]; let supplierId = supplier.id; let priceArea = supplier.priceArea; print("Fundet netselskab: " + supplierId + ", priceArea: " + priceArea); // 2. HENT PRIS-DATA FOR NUVÆRENDE TIME let now = new Date(); let year = now.getFullYear(); let month = ("0" + (now.getMonth() + 1)).slice(-2); let day = ("0" + now.getDate()).slice(-2); let hour = ("0" + now.getHours()).slice(-2); // Byg tidsstrengen for den aktuelle time (eksempel: "2025-02-02T15:00:00") let fromDate = year + "-" + month + "-" + day + "T" + hour + ":00:00"; let toDate = year + "-" + month + "-" + day + "T" + hour + ":45:00"; // URL-encoder dato-strengene let encodedFrom = myEncodeURIComponent(fromDate); let encodedTo = myEncodeURIComponent(toDate); // Byg URL'en til pris-API'en let priceUrl = "https://stromligning.dk/api/prices?from=" + encodedFrom + "&to=" + encodedTo + "&supplierId=" + supplierId + "&aggregation=1h" + "&priceArea=" + priceArea; print("Henter price-data fra: " + priceUrl); Shelly.call("HTTP.GET", { url: priceUrl }, function(priceResult, priceErrorCode, priceErrorMessage) { if (priceErrorCode !== 0) { print("Fejl ved price API GET: " + priceErrorMessage); scheduleNextPriceCheck(); return; } let data = JSON.parse(priceResult.body); if (!data.prices) { print("Ingen prisdata modtaget."); scheduleNextPriceCheck(); return; } // Find posten for den nuværende time let currentHour = now.getHours(); let found = false; data.prices.forEach(function(item) { let itemDate = new Date(item.date); let itemHour = itemDate.getHours(); if (itemHour === currentHour) { found = true; // Brug API'ets price.total (allerede inkl. moms) let priceTotal = item.price.total; // Læg evt. yderligere omkostninger oveni let finalPrice = priceTotal + CONFIG.additionalCost; // Afrund til 2 decimaler current_price = finalPrice.toFixed(2); print("Price total for den nuværende time (" + currentHour + ":00): " + current_price + " " + item.price.unit + " (inkl. yderligere omkostninger: " + CONFIG.additionalCost.toFixed(2) + " kr/kWh)"); // (Valgfrit) Skriv prisen til en virtuel enhed i Shelly GUI Shelly.call("Number.Set", { id: CONFIG.vc_id, value: current_price }); // (Valgfrit) POST prisen til en ekstern URL print("Posting price: " + current_price); Shelly.call("HTTP.REQUEST", { method: "POST", url: CONFIG.post_url, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ price: current_price }), timeout: 5000, }, function(postResult, postErrorCode, postErrorMessage) { if (postErrorCode !== 0) { print("Fejl ved POST af pris: " + postErrorMessage); } else { print("Price posted successfully: " + current_price); } }); } }); if (!found) { print("Ingen data fundet for den nuværende time (" + currentHour + ":00)."); } // Planlæg næste prisopdatering scheduleNextPriceCheck(); }); }); } /** * Planlægger næste pris-tjek (enten hvert minut eller én gang i timen), * med en ekstra forsinkelse (CONFIG.check_delay_seconds). */ function scheduleNextPriceCheck() { let now = new Date(); let delay = 0; if (CONFIG.check_every_minute === true) { // HVERT MINUT: beregn hvor mange ms til næste hele minut + ekstra forsinkelse let secondsUntilNextMinute = 60 - now.getSeconds(); let msUntilNextMinute = (secondsUntilNextMinute * 1000) - now.getMilliseconds(); delay = msUntilNextMinute + (CONFIG.check_delay_seconds * 1000); print("Scheduling next price check (minute-mode) in " + formatDelay(delay)); } else { // HVERT TIME: beregn hvor mange ms til næste hele time + ekstra forsinkelse let totalSecsNow = now.getMinutes() * 60 + now.getSeconds(); let msUntilNextHour = (3600 - totalSecsNow) * 1000 - now.getMilliseconds(); delay = msUntilNextHour + (CONFIG.check_delay_seconds * 1000); print("Scheduling next price check (hour-mode) in " + formatDelay(delay)); } nextUpdateInMs = delay; Timer.set(delay, false, function () { getCurrentPrice(); }); // Starter en log-timer, der hvert 10. minut udskriver, hvor lang tid der er til næste opdatering if (loggingIntervalTimer) { Timer.clear(loggingIntervalTimer); loggingIntervalTimer = null; } let tenMinutesInMs = 10 * 60 * 1000; loggingIntervalTimer = Timer.set(tenMinutesInMs, true, function () { nextUpdateInMs -= tenMinutesInMs; if (nextUpdateInMs <= 0) { print("No time left to next update (it should happen now)."); Timer.clear(loggingIntervalTimer); loggingIntervalTimer = null; } else { print("Time left to next update: " + formatDelay(nextUpdateInMs)); } }); } // START: Test prisen med det samme, når scriptet starter getCurrentPrice(); Indsæt scriptet ved at vælge en enhed og tryk på script ikonet Opret nyt script, giv det et navn og sæt det kopierede script ind, gem scriptet..Note: scriptet kan også nemt sættes ind fra enhedens web interface. Så skal vi have fundet din Token Gå til energi og vælg fanebladet Elpris, tryk på live ud for Elpris og find din Token API URL kopier denne..OBS! Hvis man trykker på manuelt og live igen, er der generet en ny token, som skal skrives ind i scriptet. Så indsætter du din Token, erstatter den nuværende token med din egen på linie 9OBS! Gåseøjne skal stadig være der Så skal scriptet rettes lidt til så det passer til den elpris du køber til Find længde og bredegrad Der findes flere steder på nettet, hvor man kan finde en længde og bredegrad, men i dette tilfælde kan vi ligeså godt bruge shelly appen. På en hvilken som helst enhed vælger vi tandhjul/indstillinger Tryk vælg på kort Indtast by eller naviger til din adresse OBS. Du behøver ikke at vælge din nødagtige adresse – det er nok det bare er i området Indsæt bredde og længdegrad i scriptet.. Nyttige links til at tjekke dine priser Tjek dine priser og find transmission og tarif omkostninger her:https://stromligning.dk/live Find dine tariffer her:https://tariffer.dk Også en god side til at tjekke priser (især på mobil)https://elpris.wen.dk Yderlige Script indstillinger Ikke nødvendig at ændre additional_cost: værdi (Ex. 0.168)Her indtastes dine transmision omkostninger Ekstra omkostning pr. kWh i kroner. Bliver lagt oveni den endelige pris.(hvis du har yderligere omkostninger lægges det bare oven i samme beløb). check_every_minute: true, eller falseHer skrives om du vil have den til at hente prisen , hver time, eller, hvert minut.true for at hente pris hvert minut (Bør kun bruges til test).false for at hente pris, hver time (Anbefales).(For ikke at belaste server, hvor prisen hentes bør 1 minut check kun bruges til at teste om det virker).hour_check_delay_seconds: værdi (ex 10)Her skrives, antal sekunder efter timeskiftet, hvor prischecket udføres. Sørg for at scriptet kører Til sidst skal vi have scriptet til at køre og til at starte automatisk op, hvis enheden genstartet Aktiver autostart og start ved at trykke på play knappen (Blå ring = aktiv) Afslutning og test af script Når scriptet har hentet prisen første gang skal du kunne se den under Energi -> Elpris det er nødvendig at opdaterer siden OBS! Hvis man tilgår scriptet fra enhedens webinterface, så vil man kunne se log på hvad der sker. Ekstra: Tilføj pris i Virtual Enhed Scriptet skriver også prisen til et virtuel nummerEks. Enheds ID:200 (Kan ændres i scriptet) – kræver Gen3 eller nyereMed det kan du: Få vist El-prisen som en enhed Lave handlinger baseret på El-prisen Bruge den i scener OBS. Som standard kan du kun trække en virtuel enhed ud, hvis du ønsker flere kræver der Premium. Fremgangsmåde Tryk på enheden og vælg Virtuelle Komponenter ikonet Vælg komponent og opret Virtuel komponent Vælg et Nummer Virtuel enhed Indtast de forskellige indstillinger for, hvordan enheden skal se ud (kan ændres bagefter) Obs Den første enhed vil altid starte med id:200 derefter 201, 201 osv. Vælg Grupper og opret gruppe Giv gruppen et navn Sæt hak i den virtuelle enhed du har lavet Sæt hak i udpak virtuel gruppe som enhed Det var det, nu har du en virtuel enhed der viser el-prisenDen kan tilføjes til dit dashboard, men kan også bruges til at lave handlinger, så man kan tænde og slukke en enhed ud fra el-prisen OBS Prisen vises først næste gang scriptet henter el-prisen.