Live Elpris – Dansk

Live Elpris – Dansk

Få Live Elpris ind i Shelly Appen

Ved at køre et script på en Shelly-enhed kan vi tilføje 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 også have mindst én enhed, der måler effekt (PM eller EM).
  • Brug Shelly Smart Control-appen på Android, iOS eller http://control.shelly.cloud på din pc. PC  anbefales, og det er også det, jeg selv benytter i denne guide.
  • Hvis man vil bruge funktionen Virtuelle enheder, (Trin 8) så kræves det en som minimum en Gen3, eller nyere enhed, som understøtter virtuelle enheder.

Trin 1: Kopier Script

Kopier nedenstående script
(Når musen holdes hen over kan man vælge Copy oppe i højre hjørne)

Trin 2: Indsæt Script

// Henter data fra https://stromligning.dk

//===== KONFIGURATION =====
let CONFIG = {
  // Indtast breddegrad og længdegrad 
  lat: "55.120019",       // Indtast breddegrad
  long: "12.044538",       // Indtast længdegrad
  additionalCost: 0.00,    // Yderligere omkostninger (kr/kWh), som lægges oven i price.total
  post_url: "https://shelly-t1-eu.shelly.cloud/v2/user/pp-ltu/eyJpZCI6MzQ4NzQ4LCJzbiI6MjQwMzU5MjY0NH0.MisIm5ns_TV5_LuC4-XhvQR3Awn18a5rDme-KTx7kNQ", // (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   = fromDate; // Vi henter kun data for den aktuelle time
    
    // 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 +
                   "&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();
  1. Tryk på enheden og vælg Script ikonet.
  2. Opret nyt script.
  3.  Giv det et navn og sæt det kopieret script ind.
  4. Tryk Gem (disk) og Luk (kryds)

    Note: Scriptet kan også nemt sættes ind fra enhedens web interface.

Trin 3: Find og kopier din Token

  1. Gå til “Energi” og vælg fanbladet Elpris
  2.  Tryk på Live ud for Elpris
  3. Scroll ned til API URL og kopier din Token

OBS! Hvis man trykker på Manuelt og Live igen er der genereret en ny token, som så skal skrives ind i scriptet.

Trin 4: Indsæt Token

Ved post_url på linje 9
Erstattes den nuværende Token med den du har kopieret.
OBS! Gåseøjnen skal stadig være der.

Trin 5: Find og indsæt Bredde, Længdegrad

Find Bredde og Længdegrad

Der findes flere steder på nettet, hvor man kan finde bredde og længdegrad for ens adresse/område, men dette tilfælde bruge vi Shelly appen.

  1. På en hvilken som helst enhed. Gå til indstillinger(stort tandhjul)->Geografisk placering og tidszone.
  2. Tryk på Vælg fra kort
  3. Træk makør hen i nærheden af din adresse og tryk Vælg

OBS!!  I nogle tilfælde kan der være zoomet meget ind på kortet og her skal d bare zoome ud til det kommer frem.

OBS!! Du behøver ikke at sætte makøren præcis på din adresse -det er tilstrækkeligt det bare er i området (medmindre du ligger lige på grænsen til 2 netselskaber)

Indsæt Bredde og Længdegrad

I linjern med lat og long
Erstatter du de eksisterende tal med de nye
lat: “55.67364”, // Indtast breddegrad
long: “12.568057”, // Indtast længdegrad

 

Yderlige indstillinger: (Ikke nødvendige at ændre)
additionalCost: værdi  (ex. 0.09)
Her tilføjes, hvis man har yderligere omkostninger fra sit energiselskab. (Hvis det er noget man har)
check_every_minute: true, eller false
Her 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.

Trin 6: Yderlige indstillinger: (Ikke nødvendige at ændre)

 additionalCost: værdi  (ex. 0.09)
Her tilføjes, hvis man har yderligere omkostninger fra sit energiselskab. (Hvis det er noget man har)

check_every_minute: true, eller false
Her 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.

Nyttige links til at dobbelttjekke dine priser

Tjek dine priser og find transmision 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

Interaktivt kort over Netselskaber
https://elnet.dk/nettilslutning/find-netselskab

Trin 7: Sørg for script kører

Til sidst skal vi sørge for at scriptet kører samt det automatisk starter op , hvis enheden genstarter.

  1. Gå ind under scripts.
  2. Aktiver autostart.
  3. Start script ved at trykke på play knappen.
    (Blå ring = aktiv)

 

Trin 8: Afslutning på Script opsætning

Når scriptet har hentet prisen første gang, så burde du kunne se den opdateret pris under Energi -> Elpris.
Det er nødvendigt at opdatere siden ved fx. at trykke F5

OBS! Hvis man tilgår scriptet fra enhedens web interface via dens ip, så vil du kunne se en log, hvor der står, hvad der sker og om det er det rigtige netet er det rigtige netselskanb

Vigtigt

Hvis man trykker på Manuelt og Live igen, er der genereret en ny token, som så skal skrives ind i scriptet.

Hvis det driller, så spørg gerne inde i den danske Facebookgruppe.

Ekstra: Tilføj pris i Virtual Enhed (Kræver Gen3 eller nyere)

Scriptet skriver også prisen til Virtuel “Nummer”
Enhed. Id: 200 (Dette Id nummer kan ændres i scriptet)
– Kræver Gen3, eller nyere
Med det kan du:

  • Få vist Prisen som en enhed.
  • Lave handlinger baseret på prisen.
  • Bruge den i scener. (KOMMER SNART)

OBS!
Som standard kan du kun trække én Virtuel enhed ud som enhed.
Hvis du vil have flere kræves det Premium)

Fremgangsmåde

  1. Tryk på enheden og vælg Virtuelle Komponenter ikonet.
  2. Vælg komponenter og opret Virtuelle komponent

  1. Vælg en Nummer Virtuel enhed
  2. Indtast de forskellige indstillinger for, hvordan enheden skal se ud (Det kan altid ændres bagefter)

    OBS! Den første enhed man laver vil altid starte som id:200 og derefter 201, 202 osv. 

  1. Vælg Grupper og opret gruppe.
  2. Giv gruppen et navn.
  3. Sæt hak i den Virtuelle enhed du har lavet.
  4. Sæt hak i  Udpak virtuel gruppe som enhed.

Det var det!
Du har nu Virtuel enhed der viser, hvad prisen er.
Den kan tilføjes til dit dashboard, men kan også bruges til at laves handlinger, så man kan tænde og slukke dine enheder baseret på elprisen.

OBS! Prisen vises selvfølgelige ført næste gang scriptet henter prisen.

Ekstra Ekstra: Lav automatiseringer (actions) baseret på Elpris (Kræver Gen3 eller nyere)

Kommer snart.