Live Elpris – Svenska

Live Elpris – Svenska

Få Direkta Elpriser i Shelly-appen

Genom att köra ett script på en Shelly-enhet kan vi lägga till direkta elpriser direkt i appen. På så sätt kan du enkelt få en överblick över de exakta kostnaderna för din konsumtion.

Vad man ska använda

  • Du behöver en Shelly-enhet som stöder skript (Gen2 eller senare).
  • Du måste också ha minst en enhet som mäter effekt (PM eller EM).
  • Använd Shelly Smart Control-appen på Android, iOS eller http://control.shelly.cloud på din PC. Det rekommenderas, och det är också det jag använder i den här guiden.

Steg 1: Kopiera Script

Kopiera scriptet nedan
(När du håller musen över den kan du välja Kopiera i det övre högra hörnet)

let CONFIG = {
  api_endpoint_template: "https://www.elprisetjustnu.se/api/v1/prices/{YEAR}/{DATE}_{PRICE_AREA}.json",
// ex på slut generet url https://www.elprisetjustnu.se/api/v1/prices/2025/01-08_DK2.json

// ********Inställningar nedan***********
// Välj prisområde: Sätta in i price_area:
// SE1 = Luleå / Norra Sverige
// SE2 = Sundsvall / Norra centrala Sverige
// SE3 = Stockholm / Södra centrala Sverige
// SE4 = Malmö / Södra Sverige

  price_area: "SE1",         // Välj prisområde
  include_vat: true,         // Sätt till true för att inkludera moms (25%) i priset, eller false för att exkludera moms.
  include_elafgift: true,    // Sätt till true för att inkludera elskatt i priset, eller false för att exkludera elskatt.
  elafgift: 0.72,            // Elskatt i kr/kWh (utan moms). Om include_vat är true, läggs moms även till på denna avgift.
  additional_cost: 0.164,    // Extra kostnad i kr/kWh. Lägger till detta i det slutliga priset.
  include_tariffs: false,     // är inte aktuellt i Sverige, så inställt på false
  // Endast för orter där det tillkommer en extra avgift på timpriset under vissa perioder på dygnet, tydligen inte nödvändigt i Sverige
  tariff_periods: [    
    { start: "00:01", end: "06:00", tariff: 0.0 },
   
  ],
// URL för POST
  post_url: "https://shelly-t1-eu.shelly.cloud/v2/user/pp-ltu/eyJpZCI6MzQ4NzQ4LCJzbiI6MjQwMzU5MjY0NH0.MisIm5ns_TV5_LuC4-XhvQ",
 
// Styrning av uppdateringsfrekvens
// För att inte belasta servern, där priset hämtas, bör det vara inställt på false. 1-minutskontroll bör endast användas för att testa att det fungerar.
  check_every_minute: true,  // true = varje minut, false = en gång i timmen
  check_delay_seconds: 10,    // Antal sekunder efter tim-/minutskiftet när prisuppdateringen utförs. (samma i båda lägena)
  vc_id: 200,  
};

// Här sparar vi priset (bara för referens)
let current_price = null;

// Variabler för vår loggtimer
let loggingIntervalTimer = null;  // ID för den återkommande loggtimern
let nextUpdateInMs = 0;           // Hur lång tid (i ms) till nästa uppdatering


/**
 * Hjälpfunktion:
 *  Omvandlar millisekunder till "0h 5m 10s"-format
 */
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";
}


/**
 * Hämtar den fullständiga URL-slutpunkten för vårt pris-API,
 * baserat på dagens datum.
 */
function getApiEndpoint() {
  let now = new Date();
  let year = now.getFullYear();
  let month = now.getMonth() + 1;
  let day = now.getDate();

  let formattedMonth = (month < 10 ? "0" : "") + month;
  let formattedDay = (day < 10 ? "0" : "") + day;

  return CONFIG.api_endpoint_template
    .replace("{YEAR}", year)
    .replace("{DATE}", formattedMonth + "-" + formattedDay)
    .replace("{PRICE_AREA}", CONFIG.price_area);
}


/**
 * Hittar den aktuella nätariffen (utifrån den aktuella tiden).
 */
function getCurrentTariff() {
  if (!CONFIG.include_tariffs) return 0; // Om tariffperioder inte ska inkluderas, returnera 0.

  let now = new Date();
  let currentHour = now.getHours();
  let currentMinute = now.getMinutes();

  for (let i = 0; i < CONFIG.tariff_periods.length; i++) {
    let period = CONFIG.tariff_periods[i];
    let start = period.start.split(":"), end = period.end.split(":"),
      startHour = parseInt(start[0], 10), startMinute = parseInt(start[1], 10),
      endHour = parseInt(end[0], 10), endMinute = parseInt(end[1], 10);

    if (
      (currentHour > startHour || (currentHour === startHour && currentMinute >= startMinute)) &&
      (currentHour < endHour || (currentHour === endHour && currentMinute <= endMinute))
    ) {
      return period.tariff;
    }
  }
  return 0;
}


/**
 * Hämtar aktuell pris från API, beräknar slutligt pris,
 * och skickar det via POST.
 */
function getCurrentPrice() {
  Shelly.call("http.get", { url: getApiEndpoint(), timeout: 5000 }, function (response, error_code, error_message) {
    if (error_code !== 0) {
      print("Error:", error_message);
      scheduleNextPriceCheck();
      return;
    }

    let data = JSON.parse(response.body);
    let now = new Date();
    let year = now.getFullYear();
    let month = now.getMonth() + 1;
    let day = now.getDate();
    let hour = now.getHours();

    let formattedMonth = (month < 10 ? "0" : "") + month;
    let formattedDay = (day < 10 ? "0" : "") + day;
    let formattedHour = (hour < 10 ? "0" : "") + hour;

    // Exempel: "2023-12-31T09:00:00+01:00" i data
    let currentHourStr =
      year + "-" + formattedMonth + "-" + formattedDay + "T" + formattedHour + ":00:00+01:00";

    let currentData = null;
    for (let i = 0; i < data.length; i++) {
      if (data[i].time_start === currentHourStr) {
        currentData = data[i];
        break;
      }
    }

    if (currentData) {
      let sekPerKwh = currentData["SEK_per_kWh"];

      // Tillæg moms
      if (CONFIG.include_vat) {
        sekPerKwh *= 1.25;
      }

      // Lägg till nättariff
      sekPerKwh += getCurrentTariff();

      // Lägg till elskatt
      if (CONFIG.include_elafgift) {
        let elafgift = CONFIG.elafgift;
        if (CONFIG.include_vat) {
          elafgift *= 1.25;
        }
        sekPerKwh += elafgift;
      }

      // Lägg till eventuell extra kostnad
      sekPerKwh += CONFIG.additional_cost;

      // Avrunda till 2 decimaler
      current_price = sekPerKwh.toFixed(2);
      print("Current price in kroner:", current_price);
      
      // Skriver priset till den virtuella nummerenheten som kan visas i Shelly Web GUI
      Shelly.call("Number.Set", { id: CONFIG.vc_id, value: current_price });

      // POST till Shelly 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 (postResponse, postErrorCode, postErrorMessage) {
          if (postErrorCode !== 0) {
            print("Error posting price:", postErrorMessage);
          } else {
            print("Price posted successfully:", current_price);
          }
        }
      );
    } else {
      print("No data found for the current hour:", currentHourStr);
    }

    scheduleNextPriceCheck();
  });
}


/**
 * Startar en återkommande timer som var 10:e minut loggar "Tid kvar till nästa uppdatering".
 */
function startUpdateLogging() {
  // Ryd op i evt. tidigare timer
  if (loggingIntervalTimer) {
    Timer.clear(loggingIntervalTimer);
    loggingIntervalTimer = null;
  }

  // Återkommande intervall: 10 minuter i millisekunder
  let tenMinutesInMs = 10 * 60 * 1000;

  // Sätt en återkommande timer
  loggingIntervalTimer = Timer.set(tenMinutesInMs, true, function () {
    // Varje gång timern triggas drar vi av 10 min från nextUpdateInMs
    nextUpdateInMs -= tenMinutesInMs;

    if (nextUpdateInMs <= 0) {
      // Om tiden är slut stoppar vi loggtimern
      print("No time left to next update (it should happen now).");
      Timer.clear(loggingIntervalTimer);
      loggingIntervalTimer = null;
    } else {
      // Annars loggar vi tiden
      print("Time left to next update:", formatDelay(nextUpdateInMs));
    }
  });
}


/**
 * Planerar nästa uppdatering (antingen varje minut eller en gång i timmen),
 * men använder bara EN gemensam försening, 'check_delay_seconds', i båda lägena.
 */
function scheduleNextPriceCheck() {
  let now = new Date();
  let delay = 0;

  if (CONFIG.check_every_minute === true) {
    // ---------- VARJE MINUT -----------
    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 {
    // --------- EN GÅNG I TIMMEN --------
    // Räkna manuellt ut hur många ms det är till nästa hela timme
    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));
  }

  // Spara i global variabel så vi kan logga nedräkningen
  nextUpdateInMs = delay;

  // Sätt timer för själva prisuppdateringen
  Timer.set(delay, false, function () {
    getCurrentPrice();
  });
}


// Kör skriptet allra första gången (vid uppstart)
scheduleNextPriceCheck();

Steg 2: Infoga Script

  1. Tryck på enheten och välj scriptikonen.
  2. Skapa nytt script.
  3. Ge det ett namn och klistra in det kopierade scriptet.
  4. Tryck på Spara (disk) och Stäng (kryss)

    Obs: Scriptet kan också enkelt infogas från enhetens webbgränssnitt.

Steg 3: Hitta och kopiera din Token

  1. Gå till “Energi” och välj fliken Elpris.
  2. Tryck Live bredvid Elpris.
  3. Scrolla ner till API URL och kopiera din Token.

OBS! Om du trycker på Manual och Live igen kommer en ny token att genereras, som sedan måste matas in i skriptet.

Steg 4: Infoga token

På post_url på rad 24
Byt ut den nuvarande token med den du kopierade.
OBS! Gåsögonen borde fortfarande finnas där.

Steg 5: Redigera scriptet

För att få scriptet konfigurerat för dina priser, krävs en liten modifiering.

Script beskrivning

price_area: SE1, SE2, SE3, SE4
Här skriver du vilken priszon du befinner dig i.
SE1 = Luleå / Northern Sweden
SE2 = Sundsvall / Northern Central Sweden
SE3 = Stockholm / Southern Central Sweden
SE4 = Malmö / Southern Sweden

include_vat: true, eller false
Här kan du ange om du vill visa priset inklusive moms.
true att inkludera moms (25%) i priset.
false att exkludera moms.

include_elafgift: true, eller false
Här kan du ange om du vill se priset inklusive elskatt.
true att inkludera elskatt i priset.
false att undanta elskatt.

elafgift: värde   (Ex. 0.72)
Skriv elskatten i kronor (exkl. moms) per kWh. Om include_vat är sant läggs även moms på denna skatt.
(Från och med 2025: Ex. moms = 0,72 SEK. Inkl. moms = 90 SEK.)

additional_cost: värde (Ex. 0.168)
Här anger du dina överföringskostnader. kWh i kronor. Kommer att läggas till det slutliga priset.
(om du har ytterligare kostnader, lägg dem bara till samma belopp).

include_tariffs: true, eller false
är inte aktuellt i Sverige, så inställt på false

tariff_periods:
Endast för orter där det tillkommer en extra avgift på timpriset under vissa perioder på dygnet, tydligen inte nödvändigt i Sverige
Ex. på en rad:
{ start: “00:01”, end: “06:00”, tariff: 0.14 },

check_every_minute: true, eller false
Här skriver du om du vill att den ska hämta priset varje timme, eller varje minut.
true för att hämta pris varje minut (Bör endast användas för testning).
false för att få pris, varje timme (rekommenderas).
(För att undvika att överbelasta servern där priset hämtas ska 1-minuterskontrollen endast användas för att testa om den fungerar).

hour_check_delay_seconds:
  värde (ex 10)
Här anger du antalet sekunder efter timbytet när priskontrollen utförs.

Användbara länkar för att kontrollera dina priser

Steg 6: Se till att scriptet körs

Slutligen måste vi se till att skriptet körs och att det startar automatiskt om enheten startar om.

  1. Gå under script.
  2. Aktivera autostart.
  3. Starta manuset genom att trycka på play-knappen.
    (Blå ring = aktiv)

Steg 7: Slut på skriptinställning

När manuset har hämtat priset första gången ska du kunna se det uppdaterade priset under Energi -> Elpris.
Det är nödvändigt att uppdatera sidan genom att till exempel: för att trycka på F5

OBS! Om du kommer åt skriptet från enhetens webbgränssnitt via dess IP kommer du att kunna se en logg som visar vad som händer.

Viktig

  • Om du trycker på Manual och Live igen genereras en ny token som sedan måste matas in i scriptet.
  • Priset avrundas uppåt/nedåt till 2 decimaler, så priset kan ibland skilja sig med en slant eller två, beroende på vad som anges i “additional_cost:”
  • Kom ihåg Tarifferna kan ändras flera gånger om året, så du måste justera detta manuellt.
  • Detsamma gäller om skatter och överföringskostnader m.m. ändrats.

    Om du har problem, fråga gärna i den svenska Facebookgruppen.

Extra: Lägg till pris i virtuell enhet (kräver Gen3 eller senare)

Scriptet skriver också priset till det virtuella “numret” Enhet. ID: 200 (Detta ID-nummer kan ändras i skriptet)
– Kräver Gen3 eller senare
Med den kan du:

  • Se priset som en enhet.
  • Gör åtgärder baserat på priset.
  • Använd den i scener. (KOMMER SNART)

UPPMÄRKSAMHET!
Som standard kan du bara extrahera en virtuell enhet som en enhet.
Vill du ha mer krävs Premium)

Förfarande

  1. Välj en virtuell nummerenhet.
  2. Ange de olika inställningarna för hur enheten ska se ut (Detta kan alltid ändras i efterhand)

    UPPMÄRKSAMHET! Den första enheten du skapar börjar alltid som id:200 och sedan 201, 202 osv.

  1. Välj Grupper och skapa grupp.
  2. Ge gruppen ett namn.
  3. Kontrollera den virtuella enheten du skapade.
  4. Markera rutan för Extrahera virtuell grupp som enhet.

Det var det!
Du har nu en virtuell enhet som visar vad priset är.
Den kan läggas till i din instrumentpanel, men kan också användas för att skapa åtgärder för att slå på och av dina enheter baserat på elpriset.

UPPMÄRKSAMHET! Priset kommer givetvis att visas nästa gång skriptet hämtar priset.
UPPMÄRKSAMHET! Om du vill ha en bild av gruppen som har extraherats, infogar du webbadressen till bilden från enhetens webbgränssnitt.