HomeyScript: Find automatisk den billige strøm

De fleste har nok bemærket, at prisen på strøm er steget kraftigt på det seneste. Derfor kan det, i endnu højere grad end tidligere, betale sig at holde øje med hvornår på dagen, at strømmen er billigst.

Man kan ikke længere regne med, at strømmen er billigere om natten end om dagen. Derfor er det efterhånden blevet en del af den daglige rutine at holde sig opdateret med priserne via hjemmeside eller app – og ud fra det planlægge hvornår de strømslugende apparater skal startes.

Ville det ikke være skønt, hvis Homey holdt øje med det for dig og f.eks. selv fandt de billigste 3 timer og startede apparatet der? Eller at du kunne spørge Google Assistenten hvordan strømpriserne ser ud nu og hvornår strømmen bliver billig.

Jeg har i sommers haft en pool med sandfilterpumpe og klorgenerator-anlæg, som skal køre 6-8 timer hver dag og tilsammen bruger ca. 500W. Det fik mig til at udvikle et HomeyScript, som kan gennemgå priserne på strøm, time for time, og udregne hvornår de billigste timer er og herefter tænde/slukke hver af apparaterne via en Shelly Plug S. Samme ide kan bruges til varmtvandsbeholderen, vaskemaskine, EL-bil osv.

Download af HomeyScriptet

Nyeste version er: 1.0.4 (d. 14-05-2023) som kan downloades her. (Versionsnummeret står i toppen af HomeyScriptet.)

HomeyScriptet er testet hen over sommeren af Sepp fra GeekNetWork og jeg selv, men der kan godt være fejl i det alligevel. Jeg opdaterer scriptet, hvis der findes fejl.

Homey har ikke et tag, som fortæller hvad den aktuelle time er (kl. 14:20 er den aktuelle time ”14”). Det kan løses med dette lille hjælpe HomeyScript: GetCurrentHour.js

Hjælpe-HomeyScriptet kan både bruges inline, hvor det vil retunere den aktuelle time i et lokalt tag, til brug i det videre flow – men det opdaterer også et globalt tag (Curret_Hour tag’et). Man kan derfor med fordel køre HomeyScriptet for sig selv hver time og på den måde altid have et opdateret tag til rådighed.

Ideer til flows

HomeyScriptet udfører ingen actions i sig selv. Det opretter/opdaterer kun en masse tags, som kan bruges til at bygge flows omkring. Her er en liste med ideer til de flows, som kan laves med tags’ne fra HomeyScriptet. Kommentér gerne med flere ideer, så tilføjer jeg dem til listen.

  • Start apparater i X antal timer når strømmen er billigst
    – Hvis det ikke er et smart-apparat, så husk at mange ting kan kontrolleres med Shelly Plug S, Shelly Plus 1 eller SwitchBot
  • Spørg Google Assistenten om hvordan strømpriserne er nu og få at vide hvornår strømmen er billigst (ELpris_Speak_GenerelRapport tag’et).
  • Spørg Google Assistenten om hvornår de 4 billigste timer er inden for de næste 12 timer (ELpris_Speak_FundneTimerRapport tag’et).
  • Få en statusbesked over de kommende timer om morgenen (ELpris_Speak_GenerelRapport tag’et), hvis strømmen er specielt billig i løbet af dagen.

Eksempler på flows

Jeg har svært ved at finde tiden til at skrive en lang artikel med eksempler på hvordan man benytter HomeyScriptet i praktisk. Derfor har lavet et samarbejde med Sepp fra GeekNetWork, som har lavet denne video, hvor han viser hvordan man kan bruge HomeyScriptet.

Dokumentation af ELpris HomeyScriptet

HomeyScriptet udfører ingen actions i sig selv. Det opretter/opdaterer kun en masse tags, som kan bruges til at bygge flows omkring.

Når HomeyScriptet bliver afviklet, så opdaterer det ALLE tags. Man kan ikke vælge, kun at få opdateret udvalgte tags.

I HomeyScriptet er der 2 + 24 konstanter, som du skal kontrollere og evt. ændre, før du tager det i brug:
const PriceArea = "DK2" // DK1 = Vestdanmark, DK2 = Østdanmark
const BilligPrisMinForskel = 20; // øre inkl. Moms - når der søges efter en billig periode, så skal den næste fundne periode mindst være dette antal øre billigere, for at den nye periode vælges i stedet. F.eks. Hvis 3 timers perioden fra kl. 10 til kl. 13 koster 120 øre + 231 øre + 195 øre, så skal perioden kl. 12 til 15 være dette antal øre billigere, før den periode vælges i stedet. Der regnes efter at afgifter er lagt til.

ElAfgifter[0] = 1.04 + 0.3754; // AFGIFT + TRANSPORT INKL. MOMS FRA 00:00 TIL 01:00, SOM LÆGGES OVEN I EL-PRISEN
ElAfgifter[1] = 1.04 + 0.3754; // AFGIFT + TRANSPORT INKL. MOMS FRA 01:00 TIL 02:00, SOM LÆGGES OVEN I EL-PRISEN


HomeyScriptet kan kaldes med 2 argumenter i formatet: ANTALTIMER,TIMESPAN – f.eks.: 2,14
ANTALTIMER er det antal billige timer, som du søger.
TIMESPAN er de antal timer frem fra nu, som skal undersøges. Max 24 timer.
Er klokken mere end 20 minutter inde i timen, så flyttes startpunktet 1 time frem. Er klokken f.eks. 22:15, så er periodens 14 timer fra kl. 22:00 til kl. 12:00. Er klokken senere end 22:20, så rykker perioden frem til kl. 23:00 til kl. 13:00.

Der bliver arbejdet med 2 forskellige tidsperioder i tags’ne:

  • Dagen, som er døgnet i dag, altså fra kl. 0:00 til kl. 23.59.
  • Periode, som ikke er begrænset af døgnet. Perioden tæller ”fra nu” og det ønsket antal timer frem. I perioden er også den fundne billige periode, så sørg for at læse beskrivelsen af tags’ne herunder.

Priser: Alle priser er udregnet inkl. moms og afgifter, som du indstiller i scriptet.

Beskrivelse af tags

ELpris_Opdateret_KL
Format: Text  (F.eks. ”31.8.2022 07.30.00”)
Det præcise tidspunkt, hvor HomeyScriptet blev kørt sidst.

ELpris_Dagen_Pris_Nu_KR
Format: Number decimal (F.eks. ”4.72”)
Prisen for strømmen i den time, hvor HomeyScriptet blev kørt.

ELpris_Dagen_Gennemsnitspris_KR
Format: Number decimal  (F.eks. ”4.25”)
Den gennemsnitlige pris for strømmen for hele dagen, for den dag hvor HomeyScriptet blev kørt.

ELpris_Dagen_StromBilligTil_KL
Format: Number heltal (F.eks. ”15”)
Hvis strømmen er billigere end dagens gennemsnit, i den time hvor HomeyScriptet er blevet kørt, så fortæller dette tag, hvilken time på dagen strømmen er billig til (hvornår strømmen er dyrere end dagens gennemsnit igen). Er værdien ”15”, så er strømmen billig indtil kl. 15:00.
Værdien er ”-1”, hvis nuværende time ikke er billigere end gennemsnittet.

ELpris_Dagen_StromBilligNext_KL
Format: Number heltal (F.eks. ”16”)
Hvis strømmen er dyrere end dagens gennemsnit, i den time hvor HomeyScriptet er blevet kørt, så fortæller dette tag, hvilken time på dagen strømmen bliver billig. (hvornår strømmen bliver billigere end dagens gennemsnit). Er værdien ”16”, så bliver strømmen billig kl. 16:00.
Værdien er ”-1”, hvis der ikke kommer en billigere periode senere.

ELpris_Dagen_StromBilligNext_KR
Format: Number decimal (F.eks. ”3.98”)
Hører til ELpris_Dagen_StromBilligNext_KL. Her får du oplyst hvad prisen er i den første billige time.
Værdien er ”-1”, hvis der ikke kommer en billigere periode senere.

ELpris_Dagen_StromBilligAllerBilligstNext_KL
Format: Number heltal (F.eks. ”10”)
Hører til ELpris_Dagen_StromBilligNext_KL. Her får du oplyst, hvad den billigste time er, i den kommende billige periode.
Værdien er ”-1”, hvis der ikke kommer en billigere periode senere.

ELpris_Dagen_StromBilligAllerBilligstNext_KR
Format: Number heltal (F.eks. ”10”)
Hører til ELpris_Dagen_StromBilligNext_KL. Her får du oplyst hvad prisen er i den billigste time.

ELpris_Dagen_DyresteTime_KL
Format: Number heltal  (F.eks. ”17”)
Den dyreste time på dagen

ELpris_Dagen_DyresteTime_KR
Format: Number decimal (F.eks. ”6.42”)
Prisen for den dyreste time på dagen

ELpris_Dagen_BilligsteTime_KL
Format: Number heltal (F.eks. ”12”)
Den billigste time på dagen

ELpris_Dagen_BilligsteTime_KR
Format: Number decimal (F.eks. ”5.21”)
Prisen for den billigste time på dagen.

ELpris_Periode_Undersoegt_TIMER
Format: Number heltal (F.eks. ”8”)
Det antal timer, som der er blevet undersøgt. Selvom du har bedt om at få undersøgt 14 timer, har der måske kun været data til 8 timer.

ELpris_Periode_Start_KL
Format: Number heltal (F.eks. ”6”)
Det timetal (kl. 6:00), at den billigste periode begynder

ELpris_Periode_Laengde_TIMER
Format: Number heltal (F.eks. ”8”)
Længden på den billige periode. Det tal vil altid svare til det første argument, som du har kaldt HomeyScriptet med.

ELpris_Periode_Billigste_Time_KL
Format: Number heltal (F.eks. ”13”)
Det timetal (kl. 13:00), at den billigste periode har den allerbilligste pris.

ELpris_Periode_Billigste_Time_KR
Format: Number heltal (F.eks. ”3.54”)
Hører til ELpris_Periode_Billigste_Time_KL. Prisen for den allerbilligste time i den billigste periode.

ELpris_Periode_Dyreste_Time_KL
Format: Number heltal (F.eks. ”15”)
Det timetal (kl. 15:00), at den billigste periode har den dyreste pris.

ELpris_Periode_Billigste_Time_KR
Format: Number decimal (F.eks. ”3.92”)
Hører til ELpris_Periode_Dyreste_Time_KL. Prisen for den dyreste time i den billigste periode.

ELpris_Periode_Billigste_Timer_Gennemsnitspris_KR
Format: Number decimal (F.eks. ”3.11”)
Den gennemsnitlige kWh pris for den fundne billigste periode.

ELpris_Periode_Timer_Fra_Nu_Gennemsnitspris_KR
Format: Number decimal (F.eks. ”4.56”)
Den gennemsnitlige kWh pris fra nu og de ønsket antal timer frem. Det regnes fra det minut klokken er i nu.
Er godt til at sammenligne besparelsen ved at vente til når det er billigst.

ELpris_Periode_Gennemsnitspris_KR
Format: Number decimal (F.eks. ”4.22”)
Den gennemsnitlige pris for hele den undersøgte periode – ikke kun den periode, som er valgt som den billigste. Altså perioden fra ”nu” og ”ELpris_Periode_Undersoegt_TIMER” frem.

ELpris_Speak_GenerelRapport
Format: Text (F.eks. ”Strømmen koster lige nu 7 kroner og 18 øre, og er 40 øre dyrere end dagens gennemsnit på 6 kroner og 78 øre. Dagens priser varierer fra 5 kroner og 93 øre til 8 kroner og 26 øre. Strømmen bliver billigere end gennemsnittet kl. 10, men er allerbilligst kl. 13, hvor den koster 6 kroner og 4 øre”)
Tekst som f.eks. kan bruges til Google Assistent speak eller statusrapport. Teksten udformning varierer afhængig af om det lige nu er en dyrere/billigere end gennemsnitlig time på dagen vi er i og om der kommer en dyr/billig periode senere på dagen.

ELpris_Speak_FundneTimerRapport
Format: Text (F.eks. ”Jeg har undersøgt de næste 14 timer og fundet de billigste 6 timer. Tiden starter kl. 10 og har en pris mellem 6 kroner og 4 øre, og 6 kroner og 75 øre. Strømmen koster lige nu 6 kroner og 75 øre, og er 13 øre billigere end periodens gennemsnit på 6 kroner og 88 øre.”)
Tekst som f.eks. kan bruges til Google Assistent speak eller statusrapport. Teksten udformning varierer afhængig af om det lige nu er en dyrere/billigere end gennemsnitlig time på dagen.

11 thoughts on “HomeyScript: Find automatisk den billige strøm

  • Hej Brian, Super script. Kan det udvides til at tage højde for de variable tariffer, da strømmen samlet set godt kan være dyrere på tidspunkter hvor selve elprisen er lav?

  • Hej Brian.
    Fantastisk indlæg.

    Jeg savner dog en lille ting. Gennemsnitsprisen på strømmen de sidste 3 timer…….

    Jeg laver en aflæsning når vaskemaskine, tørretumbler, opvaskemaskine er færdig. Så kunne det være fedt at jeg kunne regne prisen på den ud fra hvad strømmen har kostet.

    Håber det giver mening.

    • Hej Filip

      Det er vist et meget specifikt formål du har der – og jeg synes at det ligger uden for mit tiltænkte formål. Men koden ligger jo frit tilgængelig, så du kan rimeligt nemt udvide den med et tag med gennemsnitsprisen for de sidste 3 timer 🙂

      Personligt havde jeg nok løst det med power-by-the-hour app’en og sætte den til at måle strømforbruget på de 3 enheder live.

  • Hej Brian,
    Super arbejde 🙂

    Jeg ved ikke hvordan det er generelt, men med Konstant som el-leveranddør er der forskel på tariffer om det er sommer eller vinter.

    Jeg antager at jeg selv amå sætte en reminder om at jeg skal ind og ændre i scriptet ved sæson-skifte? 🙂

    • Hej Casper

      Hos mig er tarifferne blevet ændret mange gange i år, så må holde øje med dem hver måned.

      Det er nok en god ide, at gennemgå dem ved sæsonskifte. De stiger nok lidt år efter år alligevel. Ellers er alternativet at udbygge scriptet, så det indeholder 2 sæt priser. En simpel if, then, else ting, som kigger på datoen 🙂

  • Hej,
    Super script, men lige lidt spørgsmål 🙂

    Hvis jeg kigger i WATTS app, så er der forskellig priser / % på transport, ligner afgift fast er 1,01kr. Hvordan får jeg det til at virker i scriptet?

  • Hej
    Er der nogen der har mulighed for at opdatere dette script efter de har ændret til 15 min interval i stedet ??

    • Hej, er ikke ekspert i det her, men med hjælp af Gemini fik jeg lavet det om til 15 min intervaller:

      //---------------------------------------- FORKLARING AF DETTE SCRIPT ------------------------------------------------//

      // VERSION 1.0.1
      // * Rettet bug som gjorde, at en dag ikke var afgrænset af døgnet, men kunne strække sig længere hvis der var data nok
      // * Givet mulighed for forskellige ElAfgifter i løbet af dagen - krævet meget omkodning af scriptet, så har muligvis introduceret fejl.

      // VERSION 1.0.2
      // * Tilføjet gennemsnit kwh pris, på antal ønsket timer, hvis man starter nu i stedet for når de er billigst. Udregnet på minutbasis fra "nu". F.eks. kan 2 timer være 20 minutter i den første time, 60 minutter i den næste, og 40 minutter i den sidste.

      // VERSION 1.0.3
      // * Diverse små rettelser i udregningen af gennemsnit kwh pris

      // VERSION 1.0.4
      // * Rettet fejl pga. midlertidig udkommentering

      // VERSION 1.0.5 (Stabil version til 15-min data)
      // * Scriptet henter 15-MINUTTERS elpriser fra api.energidataservice.dk.
      // * BRUGER 'DayAheadPrices' DATASET: Selvom navnet antyder timepriser, returnerer API'et
      // 15-min data, når vi sorterer på 'TimeUTC ASC' (det korrekte 'Prices' dataset gav fejl).
      // * BRUGER 'DayAheadPriceDKK': Prisfeltet i de returnerede data hedder 'DayAheadPriceDKK'.
      // * Håndterer 96 datapunkter (kvarterer) pr. dag.
      // * Anvender timetakster fra ElAfgifter array baseret på timen for hvert kvarter (konverteret fra UTC til DK tid).
      // * Finder billigste X * 4 sammenhængende kvarterer inden for Y timer.
      // * Beregner gennemsnitspris for X timer startende fra nu ('ELpris_Periode_Timer_Fra_Nu_Gennemsnitspris_KR').
      // * Rettet logik for at finde den korrekte pris for det nuværende kvarter ('PrisLigeNu').
      // * Intern tidslogik baseret på UTC. Konverterer til lokal tid ved behov.

      // FIND DOKUMENTATION PÅ HTTPS://HOMEY.GUIDE

      // DETTE SCRIPT HENTER EL-PRISER UD FRA api.energidataservice.dk OG OPRETTER TAGS MED VÆRDIER OG SPEAKS, TIL BRUG I DET VIDERE FLOW. SCRIPTET UDFØRER INGEN HANDLINGER I SIG SELV.

      // SCRIPTET KAN BÅDE BRUGES TIL AT FÅ GENEREL INFORMATION OM EL-PRISERNE NU OG I DE KOMMENDE TIMER OG TIL AT FINDE DE BILLIGSTE X ANTAL TIMER I LØBET AF DE NÆSTE Y ANTAL TIMER. F.EKS. DE 3 BILLIGSTE TIMER TIL TØJVASK INDEN FOR DE NÆSTE 12 TIMER.

      // SCRIPTET TAGER IMOD 2 ARGUMENTER: ANTALTIMER, SOM ER DET ANTAL BILLIGE TIMER SOM DU SØGER, OG TIMESPAN SOM ER DEN PERIODE SOM SKAL UNDERSØGES. F.EKS. "2,12" FOR AT FINDE DE BILLIGSTE 2 TIMER I DE NÆSTE 12 TIMER.

      // SCRIPTET BRUGER EN SKÆRINGSTID BASERET PÅ UTC-TID: Er vi mere end 5 minutter inde i et UTC-kvarter,
      // starter søgningen fra det NÆSTE UTC-kvarter. Dette svarer ca. til den oprindelige 20-minutters
      // skæringstid i lokal tid, men er mere præcis ift. API'ets data.

      // MAX TIMESPAN ER PT. 48 TIMER.
      // DET ER IKKE ALTID AT DER ER DATA TILGÆNGELIG TIL DEN ØNSKET PERIODE, I SÅFALD HENTES DER SÅ MEGET SOM DER ER.

      //---------------------------- HERUNDER ER KONSTANTER SOM DU SKAL KONTROLLERE/ÆNDRE ----------------------------------//

      const PriceArea = "DK2" // DK1 = VESTDANMARK, DK2 = ØSTDANMARK
      const BilligPrisMinForskel = 50; // ØRE INKL. MOMS

      // ... (ElAfgifter er de samme) ...
      const ElAfgifter = new Array;
      ElAfgifter[0] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 00:00 TIL 01:00 (Lavlast)
      ElAfgifter[1] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 01:00 TIL 02:00 (Lavlast)
      ElAfgifter[2] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 02:00 TIL 03:00 (Lavlast)
      ElAfgifter[3] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 03:00 TIL 04:00 (Lavlast)
      ElAfgifter[4] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 04:00 TIL 05:00 (Lavlast)
      ElAfgifter[5] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 05:00 TIL 06:00 (Lavlast)
      ElAfgifter[6] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 06:00 TIL 07:00 (Højlast)
      ElAfgifter[7] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 07:00 TIL 08:00 (Højlast)
      ElAfgifter[8] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 08:00 TIL 09:00 (Højlast)
      ElAfgifter[9] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 09:00 TIL 10:00 (Højlast)
      ElAfgifter[10] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 10:00 TIL 11:00 (Højlast)
      ElAfgifter[11] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 11:00 TIL 12:00 (Højlast)
      ElAfgifter[12] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 12:00 TIL 13:00 (Højlast)
      ElAfgifter[13] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 13:00 TIL 14:00 (Højlast)
      ElAfgifter[14] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 14:00 TIL 15:00 (Højlast)
      ElAfgifter[15] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 15:00 TIL 16:00 (Højlast)
      ElAfgifter[16] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 16:00 TIL 17:00 (Højlast)
      ElAfgifter[17] = 1.69155; // AFGIFT + TRANSPORT INKL. MOMS FRA 17:00 TIL 18:00 (Spidslast)
      ElAfgifter[18] = 1.69155; // AFGIFT + TRANSPORT INKL. MOMS FRA 18:00 TIL 19:00 (Spidslast)
      ElAfgifter[19] = 1.69155; // AFGIFT + TRANSPORT INKL. MOMS FRA 19:00 TIL 20:00 (Spidslast)
      ElAfgifter[20] = 1.69155; // AFGIFT + TRANSPORT INKL. MOMS FRA 20:00 TIL 21:00 (Spidslast)
      ElAfgifter[21] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 21:00 TIL 22:00 (Højlast)
      ElAfgifter[22] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 22:00 TIL 23:00 (Højlast)
      ElAfgifter[23] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 23:00 TIL 00:00 (Højlast)

      //--------------------------------------------------------------------------------------------------------------------//
      // ------------------------------- DU SKAL IKKE ÆNDRE NOGET EFTER DENNE LINJE ----------------------------------------//
      //--------------------------------------------------------------------------------------------------------------------//

      // -------------- HVIS SCRIPT ER KALDT UDEN ARGUMENTS, SÅ INDSÆT STANDARD VÆRDIER -------------
      var ArgsAntalTimer, ArgsTimespan; // Disse er stadig i TIMER

      if (!args[0]) {
      ArgsAntalTimer = 2; // Antal timer billigst
      ArgsTimespan = 16; // Antal timer frem at søge i
      } else {
      const ArgsArray = args[0].split(",");
      if (ArgsArray.length != 2) { throw new Error("Der skal være præcist 2 arguments (antal timer, timespan)"); }
      ArgsAntalTimer = parseInt(ArgsArray[0]);
      ArgsTimespan = parseInt(ArgsArray[1]);
      }

      // -------------- GI'R DET MENING? - FORNUFTSTJEK -------------
      if (!ArgsAntalTimer || !ArgsTimespan) { throw new Error("Der skal indtastes 2 nummer-værdier som arguments"); }
      if (ArgsAntalTimer > ArgsTimespan) { throw new Error("Timespan skal være større end antal billige timer"); }
      if (ArgsTimespan > 48) { ArgsTimespan = 48; console.log("WARN: Timespan > 48, begrænset til 48 timer."); }
      if (ArgsAntalTimer <= 0 || ArgsTimespan = 5) {
      KvarterStartTidUTCms += 15 * 60 * 1000; // Læg 15 min til (i ms)
      KvarterStartTidUTC = new Date(KvarterStartTidUTCms);
      }

      var Timezone = (await Homey.system.getInfo()).timezone;
      console.log("Lokal tid nu: " + Nu.toLocaleString("sv-SE", { timeZone: Timezone }));
      console.log("Søgning starter fra UTC: " + KvarterStartTidUTC.toISOString().replace('T', ' ').substring(0, 19));

      // Find start dato (YYYY-MM-DD) for API kald - altid fra midnat i dag (UTC)
      var JSONDateUTC = KvarterStartTidUTC.toISOString().substring(0, 10); // YYYY-MM-DD format fra starttidspunktets UTC dato
      console.log("JSON startpoint (UTC): " + JSONDateUTC + "T00:00");

      // *** KORREKT LOGIK: Beregn API limit baseret på KVARTERER ***
      const StartTimeUTC = new Date(JSONDateUTC + "T00:00:00Z"); // Z for UTC
      const MillisekunderFraMidnatUTC = KvarterStartTidUTCms - StartTimeUTC.getTime();
      const KvarterFraMidnatIndexUTC = Math.floor(MillisekunderFraMidnatUTC / (15 * 60 * 1000));

      var JSONLimit = KvarterFraMidnatIndexUTC + ArgsTimespanKvarter + 4; // Lidt ekstra buffer

      // ----- DOWNLOAD JSON DATA FOR HELE "IDAG" + TIMESPAN (UTC) -----
      let Elpriser;
      // *** RETTELSE: Bruger 'DayAheadPrices' (da 'Prices' fejler) og sorterer på 'TimeUTC' (som giver 15-min data) ***
      const ApiUrl = `https://api.energidataservice.dk/dataset/DayAheadPrices?limit=${JSONLimit}&offset=0&start=${JSONDateUTC}T00:00&filter={%22PriceArea%22:%22${PriceArea}%22}&sort=TimeUTC%20ASC`;

      try {
      console.log('Downloader fra denne JSON URL: ' + ApiUrl);
      const response = await fetch(ApiUrl);

      if (!response.ok) {
      let errorBody = "Ukendt fejl";
      try { errorBody = await response.text(); } catch (readError) { console.log("Kunne ikke læse fejltekst:", readError); }
      console.log("Server svarede med fejl:", errorBody);
      throw new Error(`API Response error: ${response.status} ${response.statusText}`);
      }

      Elpriser = await response.json();
      console.log("JSON Response status " + response.status);

      } catch (e) {
      console.log(e);
      throw new Error("API error: Kunne ikke hente eller parse data. Oprindelig fejl: " + e.message);
      }

      // ----- TJEK OM VI FIK DATA ------
      if (Elpriser.records === undefined || Elpriser.records.length === 0) {
      throw new Error(`Energinet API returnerede 0 priser for ${JSONDateUTC} (UTC). Data-problem hos API'en.`);
      }
      console.log(`Modtog ${Elpriser.records.length} kvarters-priser fra API.`); // *** KORREKT LOGIK: kvarters-priser ***

      // ----- KONVERTER TIDER TIL LOKALE Date OBJEKTER OG FIND STARTINDEX -----
      Elpriser.records.forEach(rec => {
      if (rec.TimeUTC) { // TimeUTC er det korrekte feltnavn
      rec.Time_Local_obj = new Date(rec.TimeUTC); // Skaber Date objekt fra UTC streng
      if (isNaN(rec.Time_Local_obj.getTime())) {
      console.log(`WARN: Ugyldigt datoformat i TimeUTC '${rec.TimeUTC}'`);
      rec.Time_Local_obj = null;
      }
      } else {
      console.log("WARN: Manglende TimeUTC i record:", rec);
      rec.Time_Local_obj = null;
      }
      });

      // Find StartIndex baseret på KvarterStartTidUTCms
      let StartIndex = -1;
      for (let i = 0; i = KvarterStartTidUTCms) {
      StartIndex = i;
      break;
      }
      }

      if (StartIndex === -1) {
      let sidsteRecordTidStr = 'N/A';
      if (Elpriser.records.length > 0) {
      let lastValidRecord = Elpriser.records.slice().reverse().find(rec => rec && rec.Time_Local_obj && !isNaN(rec.Time_Local_obj.getTime()));
      if (lastValidRecord) {
      sidsteRecordTidStr = lastValidRecord.Time_Local_obj.toLocaleString('da-DK', { timeZone: Timezone });
      }
      }
      throw new Error(`Ingen fremtidige prisdata tilgængelige fra ${KvarterStartTidUTC.toLocaleTimeString('da-DK', { timeZone: Timezone })}. Sidste data kl. ${sidsteRecordTidStr}.`);
      }

      let startRecordDKTime = Elpriser.records[StartIndex] && Elpriser.records[StartIndex].Time_Local_obj ?
      Elpriser.records[StartIndex].Time_Local_obj.toLocaleString('sv-SE', { timeZone: Timezone }) : "Ugyldig tid";
      console.log(`Starter analyse fra index ${StartIndex} (lokal tid: ${startRecordDKTime})`);

      // *** VARIABEL TIL PRIS LIGE NU ***
      var PrisLigeNu = -1;

      // ----- FIND PRIS LIGE NU (KORREKT LOGIK) -----
      // Søg bagud fra StartIndex for at finde den post, der dækker NU
      let nuIndex = -1;
      // Hvis StartIndex er 0, søg fra starten. Ellers søg fra StartIndex og bagud.
      let searchStartIndex = (StartIndex > 0) ? StartIndex : 0;
      // Sørg for at vi ikke søger uden for array'ets grænser
      if (searchStartIndex >= Elpriser.records.length) {
      searchStartIndex = Elpriser.records.length - 1;
      }

      for (let ni = searchStartIndex; ni >= 0; ni--) {
      if (!Elpriser.records[ni] || !Elpriser.records[ni].Time_Local_obj) continue;
      let recordTidNu = Elpriser.records[ni].Time_Local_obj;
      if (isNaN(recordTidNu.getTime())) continue;
      if (recordTidNu.getTime() = StartIndex + ArgsAntalKvarter) {
      var DagensGennemsnitspris = 0, DagensBilligsteTime_KR = 9999999, DagensBilligsteTime_KL, DagensDyresteTime_KR = -10, DagensDyresteTime_KL;
      let DagensPriser = {};
      var PeriodeBilligst_Udregnet_KR, PeriodeBilligst_Resultat_KR, PeriodeDyrest_Udregnet_KR, PeriodeDyrest_Resultat_KR, PeriodeStarttid_Resultat_Obj, PeriodeTotalpris_Resultat = 9999999, PeriodeTotalpris_Udregnet, PeriodeGennemsnitspris = 0;
      var AntalKvarterIDagsData = 0;

      // Første loop: Find PrisLigeNu og beregn dags/periode gennemsnit + find billigste periode
      for (var i = 0; i = StartIndex && i < StartIndex + ArgsTimespanKvarter) {
      PeriodeGennemsnitspris += LoopPrisInkl;

      if (i <= Elpriser.records.length - ArgsAntalKvarter) {
      PeriodeBilligst_Udregnet_KR = 999999; PeriodeDyrest_Udregnet_KR = -10; PeriodeTotalpris_Udregnet = 0;
      let periodeErGyldig = true;

      for (let j = i; j < i + ArgsAntalKvarter; j++) {
      if (!Elpriser.records[j] || !Elpriser.records[j].Time_Local_obj) { periodeErGyldig = false; break; }
      const J_LoopDato = Elpriser.records[j].Time_Local_obj;
      if (isNaN(J_LoopDato.getTime())) { periodeErGyldig = false; break; }
      const J_LoopHour = J_LoopDato.getHours();
      // *** RETTELSE: Prisfeltet hedder 'DayAheadPriceDKK' i dette API-kald ***
      const J_LoopPrisRa = Elpriser.records[j]["DayAheadPriceDKK"] / 1000;
      if (J_LoopPrisRa === null || isNaN(J_LoopPrisRa)) { periodeErGyldig = false; break; }
      const J_LoopPris = add_moms_og_afgifter(J_LoopPrisRa, ElAfgifter[J_LoopHour]);
      if (isNaN(J_LoopPris)) { periodeErGyldig = false; break; }

      if (J_LoopPris PeriodeDyrest_Udregnet_KR) { PeriodeDyrest_Udregnet_KR = J_LoopPris; }
      PeriodeTotalpris_Udregnet += J_LoopPris;
      }

      if (periodeErGyldig) {
      const MinTotalForskel = (BilligPrisMinForskel / 100) * ArgsAntalTimer; // Forskel er stadig pr time
      if (PeriodeTotalpris_Udregnet 0) { DagensGennemsnitspris = (DagensGennemsnitspris / AntalKvarterIDagsData).toFixed(2); }
      else { DagensGennemsnitspris = 0; console.log("WARN: Ingen data for i dag."); }
      DagensBilligsteTime_KR = 9999999; DagensDyresteTime_KR = -10;
      // Beregn dags billigste/dyreste baseret på time-gennemsnit (fra kvarter-data)
      for (const time in DagensPriser) {
      let sum = DagensPriser[time].reduce((a, b) => a + b, 0);
      let avg = sum / DagensPriser[time].length;
      if (!isNaN(avg)) {
      if (avg DagensDyresteTime_KR) { DagensDyresteTime_KR = avg.toFixed(2); DagensDyresteTime_KL = time; }
      }
      }
      if (DagensBilligsteTime_KR === 9999999) DagensBilligsteTime_KR = 0;
      if (DagensDyresteTime_KR === -10) DagensDyresteTime_KR = 0;
      var DagensGennemsnitspris_kontra_pris_nu = PrisLigeNu !== -1 ? ((PrisLigeNu - DagensGennemsnitspris) * 100).toFixed(0) : 0;

      // *** KORREKT LOGIK: Bruger Kvarter-variable ***
      const FaktiskAntalKvarterUndersoegt = Math.min(ArgsTimespanKvarter, Elpriser.records.length - StartIndex);
      if (FaktiskAntalKvarterUndersoegt > 0) { PeriodeGennemsnitspris = (PeriodeGennemsnitspris / FaktiskAntalKvarterUndersoegt).toFixed(2); }
      else { PeriodeGennemsnitspris = 0; console.log("WARN: Ingen data i perioden."); }
      var PeriodeGennemsnitspris_kontra_pris_nu = PrisLigeNu !== -1 ? ((PrisLigeNu - PeriodeGennemsnitspris) * 100).toFixed(0) : 0;

      // ----- FIND DATA TIL SPEAK -----
      var Dagens_NaesteGangStroemmenBillig_KL, Dagens_NaesteGangStroemmenBillig_KR = 999999, Dagens_StroemmenBilligTil_KL;
      let fundetBilligere = false; let fundetDyrere = false;
      if (PrisLigeNu !== -1 && DagensGennemsnitspris > 0) {
      for (var i = StartIndex; i < Elpriser.records.length; i++) {
      if (!Elpriser.records[i] || !Elpriser.records[i].Time_Local_obj) continue;
      const LoopDato = Elpriser.records[i].Time_Local_obj;
      if (isNaN(LoopDato.getTime())) continue;
      const LoopHour = LoopDato.getHours();
      // *** RETTELSE: Prisfeltet hedder 'DayAheadPriceDKK' i dette API-kald ***
      const LoopPrisRa = Elpriser.records[i]["DayAheadPriceDKK"] / 1000;
      if (LoopPrisRa === null || isNaN(LoopPrisRa)) continue;
      const LoopPrisInkl = add_moms_og_afgifter(LoopPrisRa, ElAfgifter[LoopHour]);
      if (isNaN(LoopPrisInkl)) continue;

      if (LoopPrisInkl = DagensGennemsnitspris) {
      Dagens_NaesteGangStroemmenBillig_KR = LoopPrisInkl.toFixed(2);
      Dagens_NaesteGangStroemmenBillig_KL = LoopDato.toLocaleTimeString('da-DK', { hour: '2-digit', minute: '2-digit', timeZone: Timezone });
      fundetBilligere = true;
      }
      if (LoopPrisInkl >= DagensGennemsnitspris && !fundetDyrere && PrisLigeNu StartIndex) {
      let prevIdx = i - 1;
      while (prevIdx >= StartIndex && (!Elpriser.records[prevIdx] || !Elpriser.records[prevIdx].Time_Local_obj || isNaN(Elpriser.records[prevIdx].Time_Local_obj.getTime()))) { prevIdx--; }
      if (prevIdx >= StartIndex) {
      Dagens_StroemmenBilligTil_KL = LoopDato.toLocaleTimeString('da-DK', { hour: '2-digit', minute: '2-digit', timeZone: Timezone });
      } else {
      Dagens_StroemmenBilligTil_KL = LoopDato.toLocaleTimeString('da-DK', { hour: '2-digit', minute: '2-digit', timeZone: Timezone });
      }
      } else {
      Dagens_StroemmenBilligTil_KL = LoopDato.toLocaleTimeString('da-DK', { hour: '2-digit', minute: '2-digit', timeZone: Timezone });
      }
      fundetDyrere = true;
      }
      }
      }

      // *** NY BEREGNING: Beregn gennemsnitspris for X timer "fra nu" ***
      let PeriodeFraNu_Totalpris = 0;
      let PeriodeFraNu_Gennemsnitspris_KR = 0;
      let periodeFraNuErGyldig = true;

      if (Elpriser.records.length < StartIndex + ArgsAntalKvarter) {
      console.log(`WARN: Ikke nok data til at beregne 'Fra Nu' gennemsnit. Mangler ${StartIndex + ArgsAntalKvarter - Elpriser.records.length} kvarterer.`);
      periodeFraNuErGyldig = false;
      } else {
      for (let i = StartIndex; i 0) { Speak_GenerelRapport += `Det er ${Math.abs(DagensGennemsnitspris_kontra_pris_nu)} øre ${DagensGennemsnitspris_kontra_pris_nu 0) { Speak_GenerelRapport += `Dagens gennemsnit er ${DagensGennemsnitspris} kr/kWh. `; }
      if (DagensBilligsteTime_KL !== undefined && DagensDyresteTime_KL !== undefined) { Speak_GenerelRapport += `Dagens priser (timegennemsnit) varierer fra ${DagensBilligsteTime_KR} kr kl. ${DagensBilligsteTime_KL} til ${DagensDyresteTime_KR} kr kl. ${DagensDyresteTime_KL}. `; }
      if (PrisLigeNu !== -1) {
      if (DagensGennemsnitspris_kontra_pris_nu 0 && PeriodeTotalpris_Resultat !== 9999999) ? (PeriodeTotalpris_Resultat / ArgsAntalKvarter).toFixed(2) : "N/A";
      let Speak_FundneTimerRapport = `Jeg har undersøgt de næste ${FaktiskAntalKvarterUndersoegt / 4} timer og fundet de billigste ${ArgsAntalTimer} timer. `;

      if (PeriodeStarttid_Resultat_Obj) { Speak_FundneTimerRapport += `Den billigste periode starter kl. ${PeriodeStarttidFormatted} og har priser mellem ${PeriodeBilligst_Resultat_KR} kr og ${PeriodeDyrest_Resultat_KR} kr. Gennemsnitsprisen for perioden er ${PeriodeGnsSnitKr} kr/kWh. `; }
      else { Speak_FundneTimerRapport += `Kunne ikke finde en optimal periode inden for de næste ${FaktiskAntalKvarterUndersoegt / 4} timer. `; }

      if (PrisLigeNu !== -1) { Speak_FundneTimerRapport += `Strømmen koster lige nu ${PrisLigeNu} kr/kWh, hvilket er ${Math.abs(PeriodeGennemsnitspris_kontra_pris_nu)} øre ${PeriodeGennemsnitspris_kontra_pris_nu < 0 ? 'billigere' : 'dyrere'} end gennemsnittet for hele den undersøgte periode (${PeriodeGennemsnitspris} kr/kWh).`; }
      console.log('------------------------------------------------------');
      console.log(Speak_FundneTimerRapport);

      await tag("ELpris_Opdateret_KL", Nu.toLocaleString('da-DK', { hour12: false, timeZone: Timezone }));
      await tag("ELpris_Dagen_Pris_Nu_KR", Number(PrisLigeNu !== -1 ? PrisLigeNu : 0));
      await tag("ELpris_Dagen_Gennemsnitspris_KR", Number(DagensGennemsnitspris));
      await tag("ELpris_Dagen_StromBilligTil_KL", Dagens_StroemmenBilligTil_KL ? Number(Dagens_StroemmenBilligTil_KL.split(':')[0]) : -1);
      await tag("ELpris_Dagen_StromBilligNext_KL", Dagens_NaesteGangStroemmenBillig_KL ? Number(Dagens_NaesteGangStroemmenBillig_KL.split(':')[0]) : -1);
      await tag("ELpris_Dagen_StromBilligNext_KR", Dagens_NaesteGangStroemmenBillig_KR !== 999999 ? Number(Dagens_NaesteGangStroemmenBillig_KR) : 0);
      await tag("ELpris_Dagen_StromBilligAllerBilligstNext_KL", Dagens_NaesteGangStroemmenBillig_KL ? Number(Dagens_NaesteGangStroemmenBillig_KL.split(':')[0]) : -1);
      await tag("ELpris_Dagen_StromBilligAllerBilligstNext_KR", Dagens_NaesteGangStroemmenBillig_KR !== 999999 ? Number(Dagens_NaesteGangStroemmenBillig_KR) : 0);
      await tag("ELpris_Dagen_DyresteTime_KL", Number(DagensDyresteTime_KL !== undefined ? DagensDyresteTime_KL : -1));
      await tag("ELpris_Dagen_DyresteTime_KR", Number(DagensDyresteTime_KR));
      await tag("ELpris_Dagen_BilligsteTime_KL", Number(DagensBilligsteTime_KL !== undefined ? DagensBilligsteTime_KL : -1));
      await tag("ELpris_Dagen_BilligsteTime_KR", Number(DagensBilligsteTime_KR));
      await tag("ELpris_Periode_Undersoegt_TIMER", Number(FaktiskAntalKvarterUndersoegt / 4));
      await tag("ELpris_Periode_Start_KL", PeriodeStarttid_Resultat_Obj ? PeriodeStarttid_Resultat_Obj.getHours() : -1);
      await tag("ELpris_Periode_Laengde_TIMER", Number(ArgsAntalTimer));
      await tag("ELpris_Periode_Billigste_Time_KR", Number(PeriodeBilligst_Resultat_KR ? PeriodeBilligst_Resultat_KR : 0));
      await tag("ELpris_Periode_Dyreste_Time_KR", Number(PeriodeDyrest_Resultat_KR ? PeriodeDyrest_Resultat_KR : 0));
      await tag("ELpris_Periode_Billigste_Time_KL", -1);
      await tag("ELpris_Periode_Dyreste_Time_KL", -1);
      await tag("ELpris_Periode_Billigste_Timer_Gennemsnitspris_KR", Number(PeriodeGnsSnitKr !== "N/A" ? PeriodeGnsSnitKr : 0));
      await tag("ELpris_Periode_Gennemsnitspris_KR", Number(PeriodeGennemsnitspris));

      // *** RETTELSE: Opdateret tagget med den beregnede værdi ***
      await tag("ELpris_Periode_Timer_Fra_Nu_Gennemsnitspris_KR", Number(PeriodeFraNu_Gennemsnitspris_KR));
      // console.log("WARN: Tag ELpris_Periode_Timer_Fra_Nu_Gennemsnitspris_KR er ikke implementeret for 15-min data og er sat til 0."); // Fjernet advarsel

      await tag("ELpris_Speak_GenerelRapport", Speak_GenerelRapport);
      await tag("ELpris_Speak_FundneTimerRapport", Speak_FundneTimerRapport);

      } else {
      // *** KORREKT LOGIK: Bruger Kvarter-variable ***
      throw new Error(`Modtog data (${Elpriser.records.length} kvarterer), men ikke nok til at finde ${ArgsAntalKvarter} kvarterer fra start index ${StartIndex}.`);
      }

      // --------- FUNKTIONER SOM BRUGES OPPE I SCRIPTET -----------
      function add_moms_og_afgifter($brutto, $Afgifter) {
      let prisMedMomsOgAfgifter = ($brutto * 1.25) + $Afgifter;
      if (isNaN(prisMedMomsOgAfgifter)) {
      console.log(`WARN: add_moms_og_afgifter beregnede NaN. Brutto: ${$brutto}, Afgifter: ${$Afgifter}`);
      return NaN;
      }
      return Number(prisMedMomsOgAfgifter.toFixed(5));
      }

  • Hej, jeg er ikke nogen ekspert i det her, men fik hjælp fra Gemini til at lave det om til 15 min, intervaler i stedet. Ser ud til at virke for mig:

    //—————————————- FORKLARING AF DETTE SCRIPT ————————————————//

    // VERSION 1.0.1
    // * Rettet bug som gjorde, at en dag ikke var afgrænset af døgnet, men kunne strække sig længere hvis der var data nok
    // * Givet mulighed for forskellige ElAfgifter i løbet af dagen – krævet meget omkodning af scriptet, så har muligvis introduceret fejl.

    // VERSION 1.0.2
    // * Tilføjet gennemsnit kwh pris, på antal ønsket timer, hvis man starter nu i stedet for når de er billigst. Udregnet på minutbasis fra “nu”. F.eks. kan 2 timer være 20 minutter i den første time, 60 minutter i den næste, og 40 minutter i den sidste.

    // VERSION 1.0.3
    // * Diverse små rettelser i udregningen af gennemsnit kwh pris

    // VERSION 1.0.4
    // * Rettet fejl pga. midlertidig udkommentering

    // VERSION 1.0.5 (Stabil version til 15-min data)
    // * Scriptet henter 15-MINUTTERS elpriser fra api.energidataservice.dk.
    // * BRUGER ‘DayAheadPrices’ DATASET: Selvom navnet antyder timepriser, returnerer API’et
    // 15-min data, når vi sorterer på ‘TimeUTC ASC’ (det korrekte ‘Prices’ dataset gav fejl).
    // * BRUGER ‘DayAheadPriceDKK’: Prisfeltet i de returnerede data hedder ‘DayAheadPriceDKK’.
    // * Håndterer 96 datapunkter (kvarterer) pr. dag.
    // * Anvender timetakster fra ElAfgifter array baseret på timen for hvert kvarter (konverteret fra UTC til DK tid).
    // * Finder billigste X * 4 sammenhængende kvarterer inden for Y timer.
    // * Beregner gennemsnitspris for X timer startende fra nu (‘ELpris_Periode_Timer_Fra_Nu_Gennemsnitspris_KR’).
    // * Rettet logik for at finde den korrekte pris for det nuværende kvarter (‘PrisLigeNu’).
    // * Intern tidslogik baseret på UTC. Konverterer til lokal tid ved behov.

    // FIND DOKUMENTATION PÅ https://HOMEY.GUIDE

    // DETTE SCRIPT HENTER EL-PRISER UD FRA api.energidataservice.dk OG OPRETTER TAGS MED VÆRDIER OG SPEAKS, TIL BRUG I DET VIDERE FLOW. SCRIPTET UDFØRER INGEN HANDLINGER I SIG SELV.

    // SCRIPTET KAN BÅDE BRUGES TIL AT FÅ GENEREL INFORMATION OM EL-PRISERNE NU OG I DE KOMMENDE TIMER OG TIL AT FINDE DE BILLIGSTE X ANTAL TIMER I LØBET AF DE NÆSTE Y ANTAL TIMER. F.EKS. DE 3 BILLIGSTE TIMER TIL TØJVASK INDEN FOR DE NÆSTE 12 TIMER.

    // SCRIPTET TAGER IMOD 2 ARGUMENTER: ANTALTIMER, SOM ER DET ANTAL BILLIGE TIMER SOM DU SØGER, OG TIMESPAN SOM ER DEN PERIODE SOM SKAL UNDERSØGES. F.EKS. “2,12” FOR AT FINDE DE BILLIGSTE 2 TIMER I DE NÆSTE 12 TIMER.

    // SCRIPTET BRUGER EN SKÆRINGSTID BASERET PÅ UTC-TID: Er vi mere end 5 minutter inde i et UTC-kvarter,
    // starter søgningen fra det NÆSTE UTC-kvarter. Dette svarer ca. til den oprindelige 20-minutters
    // skæringstid i lokal tid, men er mere præcis ift. API’ets data.

    // MAX TIMESPAN ER PT. 48 TIMER.
    // DET ER IKKE ALTID AT DER ER DATA TILGÆNGELIG TIL DEN ØNSKET PERIODE, I SÅFALD HENTES DER SÅ MEGET SOM DER ER.

    //—————————- HERUNDER ER KONSTANTER SOM DU SKAL KONTROLLERE/ÆNDRE ———————————-//

    const PriceArea = “DK2” // DK1 = VESTDANMARK, DK2 = ØSTDANMARK
    const BilligPrisMinForskel = 50; // ØRE INKL. MOMS

    // … (ElAfgifter er de samme) …
    const ElAfgifter = new Array;
    ElAfgifter[0] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 00:00 TIL 01:00 (Lavlast)
    ElAfgifter[1] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 01:00 TIL 02:00 (Lavlast)
    ElAfgifter[2] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 02:00 TIL 03:00 (Lavlast)
    ElAfgifter[3] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 03:00 TIL 04:00 (Lavlast)
    ElAfgifter[4] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 04:00 TIL 05:00 (Lavlast)
    ElAfgifter[5] = 0.47135; // AFGIFT + TRANSPORT INKL. MOMS FRA 05:00 TIL 06:00 (Lavlast)
    ElAfgifter[6] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 06:00 TIL 07:00 (Højlast)
    ElAfgifter[7] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 07:00 TIL 08:00 (Højlast)
    ElAfgifter[8] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 08:00 TIL 09:00 (Højlast)
    ElAfgifter[9] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 09:00 TIL 10:00 (Højlast)
    ElAfgifter[10] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 10:00 TIL 11:00 (Højlast)
    ElAfgifter[11] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 11:00 TIL 12:00 (Højlast)
    ElAfgifter[12] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 12:00 TIL 13:00 (Højlast)
    ElAfgifter[13] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 13:00 TIL 14:00 (Højlast)
    ElAfgifter[14] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 14:00 TIL 15:00 (Højlast)
    ElAfgifter[15] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 15:00 TIL 16:00 (Højlast)
    ElAfgifter[16] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 16:00 TIL 17:00 (Højlast)
    ElAfgifter[17] = 1.69155; // AFGIFT + TRANSPORT INKL. MOMS FRA 17:00 TIL 18:00 (Spidslast)
    ElAfgifter[18] = 1.69155; // AFGIFT + TRANSPORT INKL. MOMS FRA 18:00 TIL 19:00 (Spidslast)
    ElAfgifter[19] = 1.69155; // AFGIFT + TRANSPORT INKL. MOMS FRA 19:00 TIL 20:00 (Spidslast)
    ElAfgifter[20] = 1.69155; // AFGIFT + TRANSPORT INKL. MOMS FRA 20:00 TIL 21:00 (Spidslast)
    ElAfgifter[21] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 21:00 TIL 22:00 (Højlast)
    ElAfgifter[22] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 22:00 TIL 23:00 (Højlast)
    ElAfgifter[23] = 0.77635; // AFGIFT + TRANSPORT INKL. MOMS FRA 23:00 TIL 00:00 (Højlast)

    //——————————————————————————————————————–//
    // ——————————- DU SKAL IKKE ÆNDRE NOGET EFTER DENNE LINJE —————————————-//
    //——————————————————————————————————————–//

    // ————– HVIS SCRIPT ER KALDT UDEN ARGUMENTS, SÅ INDSÆT STANDARD VÆRDIER ————-
    var ArgsAntalTimer, ArgsTimespan; // Disse er stadig i TIMER

    if (!args[0]) {
    ArgsAntalTimer = 2; // Antal timer billigst
    ArgsTimespan = 16; // Antal timer frem at søge i
    } else {
    const ArgsArray = args[0].split(“,”);
    if (ArgsArray.length != 2) { throw new Error(“Der skal være præcist 2 arguments (antal timer, timespan)”); }
    ArgsAntalTimer = parseInt(ArgsArray[0]);
    ArgsTimespan = parseInt(ArgsArray[1]);
    }

    // ————– GI’R DET MENING? – FORNUFTSTJEK ————-
    if (!ArgsAntalTimer || !ArgsTimespan) { throw new Error(“Der skal indtastes 2 nummer-værdier som arguments”); }
    if (ArgsAntalTimer > ArgsTimespan) { throw new Error(“Timespan skal være større end antal billige timer”); }
    if (ArgsTimespan > 48) { ArgsTimespan = 48; console.log(“WARN: Timespan > 48, begrænset til 48 timer.”); }
    if (ArgsAntalTimer <= 0 || ArgsTimespan = 5) {
    KvarterStartTidUTCms += 15 * 60 * 1000; // Læg 15 min til (i ms)
    KvarterStartTidUTC = new Date(KvarterStartTidUTCms);
    }

    var Timezone = (await Homey.system.getInfo()).timezone;
    console.log(“Lokal tid nu: ” + Nu.toLocaleString(“sv-SE”, { timeZone: Timezone }));
    console.log(“Søgning starter fra UTC: ” + KvarterStartTidUTC.toISOString().replace(‘T’, ‘ ‘).substring(0, 19));

    // Find start dato (YYYY-MM-DD) for API kald – altid fra midnat i dag (UTC)
    var JSONDateUTC = KvarterStartTidUTC.toISOString().substring(0, 10); // YYYY-MM-DD format fra starttidspunktets UTC dato
    console.log(“JSON startpoint (UTC): ” + JSONDateUTC + “T00:00”);

    // *** KORREKT LOGIK: Beregn API limit baseret på KVARTERER ***
    const StartTimeUTC = new Date(JSONDateUTC + “T00:00:00Z”); // Z for UTC
    const MillisekunderFraMidnatUTC = KvarterStartTidUTCms – StartTimeUTC.getTime();
    const KvarterFraMidnatIndexUTC = Math.floor(MillisekunderFraMidnatUTC / (15 * 60 * 1000));

    var JSONLimit = KvarterFraMidnatIndexUTC + ArgsTimespanKvarter + 4; // Lidt ekstra buffer

    // —– DOWNLOAD JSON DATA FOR HELE “IDAG” + TIMESPAN (UTC) —–
    let Elpriser;
    // *** RETTELSE: Bruger ‘DayAheadPrices’ (da ‘Prices’ fejler) og sorterer på ‘TimeUTC’ (som giver 15-min data) ***
    const ApiUrl = `https://api.energidataservice.dk/dataset/DayAheadPrices?limit=${JSONLimit}&offset=0&start=${JSONDateUTC}T00:00&filter={%22PriceArea%22:%22${PriceArea}%22}&sort=TimeUTC%20ASC`;

    try {
    console.log(‘Downloader fra denne JSON URL: ‘ + ApiUrl);
    const response = await fetch(ApiUrl);

    if (!response.ok) {
    let errorBody = “Ukendt fejl”;
    try { errorBody = await response.text(); } catch (readError) { console.log(“Kunne ikke læse fejltekst:”, readError); }
    console.log(“Server svarede med fejl:”, errorBody);
    throw new Error(`API Response error: ${response.status} ${response.statusText}`);
    }

    Elpriser = await response.json();
    console.log(“JSON Response status ” + response.status);

    } catch (e) {
    console.log(e);
    throw new Error(“API error: Kunne ikke hente eller parse data. Oprindelig fejl: ” + e.message);
    }

    // —– TJEK OM VI FIK DATA ——
    if (Elpriser.records === undefined || Elpriser.records.length === 0) {
    throw new Error(`Energinet API returnerede 0 priser for ${JSONDateUTC} (UTC). Data-problem hos API’en.`);
    }
    console.log(`Modtog ${Elpriser.records.length} kvarters-priser fra API.`); // *** KORREKT LOGIK: kvarters-priser ***

    // —– KONVERTER TIDER TIL LOKALE Date OBJEKTER OG FIND STARTINDEX —–
    Elpriser.records.forEach(rec => {
    if (rec.TimeUTC) { // TimeUTC er det korrekte feltnavn
    rec.Time_Local_obj = new Date(rec.TimeUTC); // Skaber Date objekt fra UTC streng
    if (isNaN(rec.Time_Local_obj.getTime())) {
    console.log(`WARN: Ugyldigt datoformat i TimeUTC ‘${rec.TimeUTC}’`);
    rec.Time_Local_obj = null;
    }
    } else {
    console.log(“WARN: Manglende TimeUTC i record:”, rec);
    rec.Time_Local_obj = null;
    }
    });

    // Find StartIndex baseret på KvarterStartTidUTCms
    let StartIndex = -1;
    for (let i = 0; i = KvarterStartTidUTCms) {
    StartIndex = i;
    break;
    }
    }

    if (StartIndex === -1) {
    let sidsteRecordTidStr = ‘N/A’;
    if (Elpriser.records.length > 0) {
    let lastValidRecord = Elpriser.records.slice().reverse().find(rec => rec && rec.Time_Local_obj && !isNaN(rec.Time_Local_obj.getTime()));
    if (lastValidRecord) {
    sidsteRecordTidStr = lastValidRecord.Time_Local_obj.toLocaleString(‘da-DK’, { timeZone: Timezone });
    }
    }
    throw new Error(`Ingen fremtidige prisdata tilgængelige fra ${KvarterStartTidUTC.toLocaleTimeString(‘da-DK’, { timeZone: Timezone })}. Sidste data kl. ${sidsteRecordTidStr}.`);
    }

    let startRecordDKTime = Elpriser.records[StartIndex] && Elpriser.records[StartIndex].Time_Local_obj ?
    Elpriser.records[StartIndex].Time_Local_obj.toLocaleString(‘sv-SE’, { timeZone: Timezone }) : “Ugyldig tid”;
    console.log(`Starter analyse fra index ${StartIndex} (lokal tid: ${startRecordDKTime})`);

    // *** VARIABEL TIL PRIS LIGE NU ***
    var PrisLigeNu = -1;

    // —– FIND PRIS LIGE NU (KORREKT LOGIK) —–
    // Søg bagud fra StartIndex for at finde den post, der dækker NU
    let nuIndex = -1;
    // Hvis StartIndex er 0, søg fra starten. Ellers søg fra StartIndex og bagud.
    let searchStartIndex = (StartIndex > 0) ? StartIndex : 0;
    // Sørg for at vi ikke søger uden for array’ets grænser
    if (searchStartIndex >= Elpriser.records.length) {
    searchStartIndex = Elpriser.records.length – 1;
    }

    for (let ni = searchStartIndex; ni >= 0; ni–) {
    if (!Elpriser.records[ni] || !Elpriser.records[ni].Time_Local_obj) continue;
    let recordTidNu = Elpriser.records[ni].Time_Local_obj;
    if (isNaN(recordTidNu.getTime())) continue;
    if (recordTidNu.getTime() = StartIndex + ArgsAntalKvarter) {
    var DagensGennemsnitspris = 0, DagensBilligsteTime_KR = 9999999, DagensBilligsteTime_KL, DagensDyresteTime_KR = -10, DagensDyresteTime_KL;
    let DagensPriser = {};
    var PeriodeBilligst_Udregnet_KR, PeriodeBilligst_Resultat_KR, PeriodeDyrest_Udregnet_KR, PeriodeDyrest_Resultat_KR, PeriodeStarttid_Resultat_Obj, PeriodeTotalpris_Resultat = 9999999, PeriodeTotalpris_Udregnet, PeriodeGennemsnitspris = 0;
    var AntalKvarterIDagsData = 0;

    // Første loop: Find PrisLigeNu og beregn dags/periode gennemsnit + find billigste periode
    for (var i = 0; i = StartIndex && i < StartIndex + ArgsTimespanKvarter) {
    PeriodeGennemsnitspris += LoopPrisInkl;

    if (i <= Elpriser.records.length – ArgsAntalKvarter) {
    PeriodeBilligst_Udregnet_KR = 999999; PeriodeDyrest_Udregnet_KR = -10; PeriodeTotalpris_Udregnet = 0;
    let periodeErGyldig = true;

    for (let j = i; j < i + ArgsAntalKvarter; j++) {
    if (!Elpriser.records[j] || !Elpriser.records[j].Time_Local_obj) { periodeErGyldig = false; break; }
    const J_LoopDato = Elpriser.records[j].Time_Local_obj;
    if (isNaN(J_LoopDato.getTime())) { periodeErGyldig = false; break; }
    const J_LoopHour = J_LoopDato.getHours();
    // *** RETTELSE: Prisfeltet hedder 'DayAheadPriceDKK' i dette API-kald ***
    const J_LoopPrisRa = Elpriser.records[j]["DayAheadPriceDKK"] / 1000;
    if (J_LoopPrisRa === null || isNaN(J_LoopPrisRa)) { periodeErGyldig = false; break; }
    const J_LoopPris = add_moms_og_afgifter(J_LoopPrisRa, ElAfgifter[J_LoopHour]);
    if (isNaN(J_LoopPris)) { periodeErGyldig = false; break; }

    if (J_LoopPris PeriodeDyrest_Udregnet_KR) { PeriodeDyrest_Udregnet_KR = J_LoopPris; }
    PeriodeTotalpris_Udregnet += J_LoopPris;
    }

    if (periodeErGyldig) {
    const MinTotalForskel = (BilligPrisMinForskel / 100) * ArgsAntalTimer; // Forskel er stadig pr time
    if (PeriodeTotalpris_Udregnet 0) { DagensGennemsnitspris = (DagensGennemsnitspris / AntalKvarterIDagsData).toFixed(2); }
    else { DagensGennemsnitspris = 0; console.log(“WARN: Ingen data for i dag.”); }
    DagensBilligsteTime_KR = 9999999; DagensDyresteTime_KR = -10;
    // Beregn dags billigste/dyreste baseret på time-gennemsnit (fra kvarter-data)
    for (const time in DagensPriser) {
    let sum = DagensPriser[time].reduce((a, b) => a + b, 0);
    let avg = sum / DagensPriser[time].length;
    if (!isNaN(avg)) {
    if (avg DagensDyresteTime_KR) { DagensDyresteTime_KR = avg.toFixed(2); DagensDyresteTime_KL = time; }
    }
    }
    if (DagensBilligsteTime_KR === 9999999) DagensBilligsteTime_KR = 0;
    if (DagensDyresteTime_KR === -10) DagensDyresteTime_KR = 0;
    var DagensGennemsnitspris_kontra_pris_nu = PrisLigeNu !== -1 ? ((PrisLigeNu – DagensGennemsnitspris) * 100).toFixed(0) : 0;

    // *** KORREKT LOGIK: Bruger Kvarter-variable ***
    const FaktiskAntalKvarterUndersoegt = Math.min(ArgsTimespanKvarter, Elpriser.records.length – StartIndex);
    if (FaktiskAntalKvarterUndersoegt > 0) { PeriodeGennemsnitspris = (PeriodeGennemsnitspris / FaktiskAntalKvarterUndersoegt).toFixed(2); }
    else { PeriodeGennemsnitspris = 0; console.log(“WARN: Ingen data i perioden.”); }
    var PeriodeGennemsnitspris_kontra_pris_nu = PrisLigeNu !== -1 ? ((PrisLigeNu – PeriodeGennemsnitspris) * 100).toFixed(0) : 0;

    // —– FIND DATA TIL SPEAK —–
    var Dagens_NaesteGangStroemmenBillig_KL, Dagens_NaesteGangStroemmenBillig_KR = 999999, Dagens_StroemmenBilligTil_KL;
    let fundetBilligere = false; let fundetDyrere = false;
    if (PrisLigeNu !== -1 && DagensGennemsnitspris > 0) {
    for (var i = StartIndex; i < Elpriser.records.length; i++) {
    if (!Elpriser.records[i] || !Elpriser.records[i].Time_Local_obj) continue;
    const LoopDato = Elpriser.records[i].Time_Local_obj;
    if (isNaN(LoopDato.getTime())) continue;
    const LoopHour = LoopDato.getHours();
    // *** RETTELSE: Prisfeltet hedder 'DayAheadPriceDKK' i dette API-kald ***
    const LoopPrisRa = Elpriser.records[i]["DayAheadPriceDKK"] / 1000;
    if (LoopPrisRa === null || isNaN(LoopPrisRa)) continue;
    const LoopPrisInkl = add_moms_og_afgifter(LoopPrisRa, ElAfgifter[LoopHour]);
    if (isNaN(LoopPrisInkl)) continue;

    if (LoopPrisInkl = DagensGennemsnitspris) {
    Dagens_NaesteGangStroemmenBillig_KR = LoopPrisInkl.toFixed(2);
    Dagens_NaesteGangStroemmenBillig_KL = LoopDato.toLocaleTimeString(‘da-DK’, { hour: ‘2-digit’, minute: ‘2-digit’, timeZone: Timezone });
    fundetBilligere = true;
    }
    if (LoopPrisInkl >= DagensGennemsnitspris && !fundetDyrere && PrisLigeNu StartIndex) {
    let prevIdx = i – 1;
    while (prevIdx >= StartIndex && (!Elpriser.records[prevIdx] || !Elpriser.records[prevIdx].Time_Local_obj || isNaN(Elpriser.records[prevIdx].Time_Local_obj.getTime()))) { prevIdx–; }
    if (prevIdx >= StartIndex) {
    Dagens_StroemmenBilligTil_KL = LoopDato.toLocaleTimeString(‘da-DK’, { hour: ‘2-digit’, minute: ‘2-digit’, timeZone: Timezone });
    } else {
    Dagens_StroemmenBilligTil_KL = LoopDato.toLocaleTimeString(‘da-DK’, { hour: ‘2-digit’, minute: ‘2-digit’, timeZone: Timezone });
    }
    } else {
    Dagens_StroemmenBilligTil_KL = LoopDato.toLocaleTimeString(‘da-DK’, { hour: ‘2-digit’, minute: ‘2-digit’, timeZone: Timezone });
    }
    fundetDyrere = true;
    }
    }
    }

    // *** NY BEREGNING: Beregn gennemsnitspris for X timer “fra nu” ***
    let PeriodeFraNu_Totalpris = 0;
    let PeriodeFraNu_Gennemsnitspris_KR = 0;
    let periodeFraNuErGyldig = true;

    if (Elpriser.records.length < StartIndex + ArgsAntalKvarter) {
    console.log(`WARN: Ikke nok data til at beregne 'Fra Nu' gennemsnit. Mangler ${StartIndex + ArgsAntalKvarter – Elpriser.records.length} kvarterer.`);
    periodeFraNuErGyldig = false;
    } else {
    for (let i = StartIndex; i 0) { Speak_GenerelRapport += `Det er ${Math.abs(DagensGennemsnitspris_kontra_pris_nu)} øre ${DagensGennemsnitspris_kontra_pris_nu 0) { Speak_GenerelRapport += `Dagens gennemsnit er ${DagensGennemsnitspris} kr/kWh. `; }
    if (DagensBilligsteTime_KL !== undefined && DagensDyresteTime_KL !== undefined) { Speak_GenerelRapport += `Dagens priser (timegennemsnit) varierer fra ${DagensBilligsteTime_KR} kr kl. ${DagensBilligsteTime_KL} til ${DagensDyresteTime_KR} kr kl. ${DagensDyresteTime_KL}. `; }
    if (PrisLigeNu !== -1) {
    if (DagensGennemsnitspris_kontra_pris_nu 0 && PeriodeTotalpris_Resultat !== 9999999) ? (PeriodeTotalpris_Resultat / ArgsAntalKvarter).toFixed(2) : “N/A”;
    let Speak_FundneTimerRapport = `Jeg har undersøgt de næste ${FaktiskAntalKvarterUndersoegt / 4} timer og fundet de billigste ${ArgsAntalTimer} timer. `;

    if (PeriodeStarttid_Resultat_Obj) { Speak_FundneTimerRapport += `Den billigste periode starter kl. ${PeriodeStarttidFormatted} og har priser mellem ${PeriodeBilligst_Resultat_KR} kr og ${PeriodeDyrest_Resultat_KR} kr. Gennemsnitsprisen for perioden er ${PeriodeGnsSnitKr} kr/kWh. `; }
    else { Speak_FundneTimerRapport += `Kunne ikke finde en optimal periode inden for de næste ${FaktiskAntalKvarterUndersoegt / 4} timer. `; }

    if (PrisLigeNu !== -1) { Speak_FundneTimerRapport += `Strømmen koster lige nu ${PrisLigeNu} kr/kWh, hvilket er ${Math.abs(PeriodeGennemsnitspris_kontra_pris_nu)} øre ${PeriodeGennemsnitspris_kontra_pris_nu < 0 ? 'billigere' : 'dyrere'} end gennemsnittet for hele den undersøgte periode (${PeriodeGennemsnitspris} kr/kWh).`; }
    console.log('——————————————————');
    console.log(Speak_FundneTimerRapport);

    await tag("ELpris_Opdateret_KL", Nu.toLocaleString('da-DK', { hour12: false, timeZone: Timezone }));
    await tag("ELpris_Dagen_Pris_Nu_KR", Number(PrisLigeNu !== -1 ? PrisLigeNu : 0));
    await tag("ELpris_Dagen_Gennemsnitspris_KR", Number(DagensGennemsnitspris));
    await tag("ELpris_Dagen_StromBilligTil_KL", Dagens_StroemmenBilligTil_KL ? Number(Dagens_StroemmenBilligTil_KL.split(':')[0]) : -1);
    await tag("ELpris_Dagen_StromBilligNext_KL", Dagens_NaesteGangStroemmenBillig_KL ? Number(Dagens_NaesteGangStroemmenBillig_KL.split(':')[0]) : -1);
    await tag("ELpris_Dagen_StromBilligNext_KR", Dagens_NaesteGangStroemmenBillig_KR !== 999999 ? Number(Dagens_NaesteGangStroemmenBillig_KR) : 0);
    await tag("ELpris_Dagen_StromBilligAllerBilligstNext_KL", Dagens_NaesteGangStroemmenBillig_KL ? Number(Dagens_NaesteGangStroemmenBillig_KL.split(':')[0]) : -1);
    await tag("ELpris_Dagen_StromBilligAllerBilligstNext_KR", Dagens_NaesteGangStroemmenBillig_KR !== 999999 ? Number(Dagens_NaesteGangStroemmenBillig_KR) : 0);
    await tag("ELpris_Dagen_DyresteTime_KL", Number(DagensDyresteTime_KL !== undefined ? DagensDyresteTime_KL : -1));
    await tag("ELpris_Dagen_DyresteTime_KR", Number(DagensDyresteTime_KR));
    await tag("ELpris_Dagen_BilligsteTime_KL", Number(DagensBilligsteTime_KL !== undefined ? DagensBilligsteTime_KL : -1));
    await tag("ELpris_Dagen_BilligsteTime_KR", Number(DagensBilligsteTime_KR));
    await tag("ELpris_Periode_Undersoegt_TIMER", Number(FaktiskAntalKvarterUndersoegt / 4));
    await tag("ELpris_Periode_Start_KL", PeriodeStarttid_Resultat_Obj ? PeriodeStarttid_Resultat_Obj.getHours() : -1);
    await tag("ELpris_Periode_Laengde_TIMER", Number(ArgsAntalTimer));
    await tag("ELpris_Periode_Billigste_Time_KR", Number(PeriodeBilligst_Resultat_KR ? PeriodeBilligst_Resultat_KR : 0));
    await tag("ELpris_Periode_Dyreste_Time_KR", Number(PeriodeDyrest_Resultat_KR ? PeriodeDyrest_Resultat_KR : 0));
    await tag("ELpris_Periode_Billigste_Time_KL", -1);
    await tag("ELpris_Periode_Dyreste_Time_KL", -1);
    await tag("ELpris_Periode_Billigste_Timer_Gennemsnitspris_KR", Number(PeriodeGnsSnitKr !== "N/A" ? PeriodeGnsSnitKr : 0));
    await tag("ELpris_Periode_Gennemsnitspris_KR", Number(PeriodeGennemsnitspris));

    // *** RETTELSE: Opdateret tagget med den beregnede værdi ***
    await tag("ELpris_Periode_Timer_Fra_Nu_Gennemsnitspris_KR", Number(PeriodeFraNu_Gennemsnitspris_KR));
    // console.log("WARN: Tag ELpris_Periode_Timer_Fra_Nu_Gennemsnitspris_KR er ikke implementeret for 15-min data og er sat til 0."); // Fjernet advarsel

    await tag("ELpris_Speak_GenerelRapport", Speak_GenerelRapport);
    await tag("ELpris_Speak_FundneTimerRapport", Speak_FundneTimerRapport);

    } else {
    // *** KORREKT LOGIK: Bruger Kvarter-variable ***
    throw new Error(`Modtog data (${Elpriser.records.length} kvarterer), men ikke nok til at finde ${ArgsAntalKvarter} kvarterer fra start index ${StartIndex}.`);
    }

    // ——— FUNKTIONER SOM BRUGES OPPE I SCRIPTET ———–
    function add_moms_og_afgifter($brutto, $Afgifter) {
    let prisMedMomsOgAfgifter = ($brutto * 1.25) + $Afgifter;
    if (isNaN(prisMedMomsOgAfgifter)) {
    console.log(`WARN: add_moms_og_afgifter beregnede NaN. Brutto: ${$brutto}, Afgifter: ${$Afgifter}`);
    return NaN;
    }
    return Number(prisMedMomsOgAfgifter.toFixed(5));
    }

Skriv en kommentar

Skriv et svar til Filip Annuller svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *