# Finding the best energy price with API call

**URL:** <https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070>\
**Category:** General\
**Created:** [29 August 2022 15:29 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070 "2022-08-29T15:29:38Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kimovitzh](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kimovitzh/32/67046_2.png) [@Kimovitzh](https://discourse.nodered.org/u/Kimovitzh)\
**Post date:** [29 August 2022 15:29 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/1 "2022-08-29T15:29:38Z")

</div>

With the current energy prices I want to see when it's most favorable to do energy heavy stuff.  
Here in Denmark we can make API call to a data hub to see energy prices at an hourly rate for current day and for the next day.

So potentially 48h in to the future if the API call I made at 00.01 o'clock.

For this I make the API call at [https://api.energidataservice.dk/dataset/Elspotprices?start=now&filter={"PriceArea":"DK2"}&sort=HourDK](https://api.energidataservice.dk/dataset/Elspotprices?start=now&filter=%7B%22PriceArea%22:%22DK2%22%7D&sort=HourDK)

```auto
[{"id":"0c9e143f916d7ede","type":"debug","z":"f6979629ded1c46f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1410,"y":4560,"wires":[]},{"id":"3845925bb4cff5e5","type":"http request","z":"f6979629ded1c46f","name":"","method":"GET","ret":"obj","paytoqs":"body","url":"https://api.energidataservice.dk/dataset/Elspotprices?start=now&filter={\"PriceArea\":\"DK2\"}&sort=HourDK","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"credentials":{},"x":1250,"y":4560,"wires":[["0c9e143f916d7ede","e69e27a90f604234","af8a879cb2b7a03b","42163f5a.825ce","4792c3d34e5a365c","8591e13802f229bf","3a8202f34b4da043","d3b5cf5afb235a3a","16042cbb2499e48f","8a6a9b0be8d02f56","4e2a7ae4eff15af9","049e024c256058ba","5279adbe98f9a23d","545f83c293705e1c"]]},{"id":"a9307deb28e64897","type":"inject","z":"f6979629ded1c46f","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1530,"y":4140,"wires":[["3845925bb4cff5e5"]]}]

```

As you can see in this example the array is 30 because there's 6 hours left of today, and 24 of tomorrow:

 ![Skærmbillede 2022-08-29 kl. 17.23.35](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/0/b0afb45d1e5ad8fc7801420abbe96f3f90a9647d.png)

What I would like to do is find the lowest "SpotPriceDKK:" in the array, and also know at what time it is.  
So that way I can see that the lowest price is in x-time.

Even better if I can filter it out to what is the lowest price in a time frame I specified.

Any ideas?

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [29 August 2022 16:18 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/2 "2022-08-29T16:18:51Z")

</div>

Hello ..  
you can do this with some Javascript in a Function node

```auto
let lowestPrice = msg.payload.records[0]; // start with 1st element

msg.payload.records.forEach(el => {
    if (el.SpotPriceDKK < lowestPrice.SpotPriceDKK) { lowestPrice = el }
})

return { payload: lowestPrice };

```

you can start by setting the lowerPrice to the first element in the records array and then loop through it with the forEach method checking each element if it is lower that the already set `lowestPrice`

**Test Flow:**

```auto
[{"id":"0c9e143f916d7ede","type":"debug","z":"54efb553244c241f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":810,"y":1600,"wires":[]},{"id":"3845925bb4cff5e5","type":"http request","z":"54efb553244c241f","name":"","method":"GET","ret":"obj","paytoqs":"body","url":"https://api.energidataservice.dk/dataset/Elspotprices?start=now&filter={\"PriceArea\":\"DK2\"}&sort=HourDK","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":450,"y":1600,"wires":[["44022b394e443ada","f5fa3a19fb71df29"]]},{"id":"a9307deb28e64897","type":"inject","z":"54efb553244c241f","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":290,"y":1600,"wires":[["3845925bb4cff5e5"]]},{"id":"44022b394e443ada","type":"function","z":"54efb553244c241f","name":"find lowest price","func":"let lowestPrice = msg.payload.records[0]; // start with 1st element\n\nmsg.payload.records.forEach(el => {\n if (el.SpotPriceDKK < lowestPrice.SpotPriceDKK) { lowestPrice = el }\n})\n\nreturn { payload: lowestPrice };","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":640,"y":1600,"wires":[["0c9e143f916d7ede"]]},{"id":"f5fa3a19fb71df29","type":"debug","z":"54efb553244c241f","name":"debug","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":600,"y":1520,"wires":[]}]

```

---

<div class="post-metadata">

**Author:** ![Kimovitzh](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kimovitzh/32/67046_2.png) [@Kimovitzh](https://discourse.nodered.org/u/Kimovitzh)\
**Post date:** [29 August 2022 16:46 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/3 "2022-08-29T16:46:48Z")

</div>

Once again you come to the rescue! Thanks mate!

I might be a bit dim, but is there a way to give a input to only look at element 1-16 or 3-10 etc.?

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [29 August 2022 17:00 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/4 "2022-08-29T17:00:30Z")

</div>

hmm .. possibly introduce in the forEach loop the `index` of the iterated element and check if its between those values ?

```auto
msg.payload.records.forEach( (el, index) => {
    if ( index >= 1 && index <= 16 && el.SpotPriceDKK < lowestPrice.SpotPriceDKK) { lowestPrice = el }
})

```

---

<div class="post-metadata">

**Author:** ![Kimovitzh](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kimovitzh/32/67046_2.png) [@Kimovitzh](https://discourse.nodered.org/u/Kimovitzh)\
**Post date:** [29 August 2022 17:12 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/5 "2022-08-29T17:12:00Z")

</div>

That seems to do the job!

That way I can set a specific time to inject and make a time frame within the current day and the day after or both to see what time I must favorable.

The time is a string, and I haven't found a solution to use that to start a flow at that time. Is it possible at all? Or is it better to use the array number as an indicator for when to fire the flow?

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [29 August 2022 17:18 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/6 "2022-08-29T17:18:40Z")

</div>

> [@Kimovitzh](#):
>
> I haven't found a solution to use that to start a flow at that time.

you mean 1 minute past midnight ?  
the Inject node has some scheduling capabilities

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/6/a6b6980449ad2dbe6d02c2eaebe1d2314cd04d95.png)

or you can use [cron-plus node](https://flows.nodered.org/node/node-red-contrib-cron-plus) for more advanced schedules

---

<div class="post-metadata">

**Author:** ![Kimovitzh](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kimovitzh/32/67046_2.png) [@Kimovitzh](https://discourse.nodered.org/u/Kimovitzh)\
**Post date:** [29 August 2022 17:27 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/7 "2022-08-29T17:27:25Z")

</div>

No, I mean the time that I get attached to the lowest price -

 ![Skærmbillede 2022-08-29 kl. 19.26.33](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/5/5596cc072e29aeeeeb582985aaf621e39e1b9a79.png)

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [29 August 2022 17:41 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/8 "2022-08-29T17:41:33Z")

</div>

oh i see .. in that case Cron-plus can do that .. with a specially crafted msg you can create dynamic schedules based on that string date coming in from the previous msg.

Example

```auto
[{"id":"0c9e143f916d7ede","type":"debug","z":"54efb553244c241f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":870,"y":1600,"wires":[]},{"id":"3845925bb4cff5e5","type":"http request","z":"54efb553244c241f","name":"","method":"GET","ret":"obj","paytoqs":"body","url":"https://api.energidataservice.dk/dataset/Elspotprices?start=now&filter={\"PriceArea\":\"DK2\"}&sort=HourDK","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":450,"y":1600,"wires":[["44022b394e443ada","f5fa3a19fb71df29"]]},{"id":"a9307deb28e64897","type":"inject","z":"54efb553244c241f","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":290,"y":1600,"wires":[["3845925bb4cff5e5"]]},{"id":"44022b394e443ada","type":"function","z":"54efb553244c241f","name":"find lowest price","func":"let lowestPrice = msg.payload.records[0]; // start with 1st element\n\nmsg.payload.records.forEach( (el, index) => {\n if ( index >= 1 && index <= 16 && el.SpotPriceDKK < lowestPrice.SpotPriceDKK) { lowestPrice = el }\n})\n\nreturn { payload: lowestPrice };","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":640,"y":1600,"wires":[["0c9e143f916d7ede","9470c79839117bff"]]},{"id":"f5fa3a19fb71df29","type":"debug","z":"54efb553244c241f","name":"debug","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":600,"y":1520,"wires":[]},{"id":"fb61b81a73fe42ee","type":"cronplus","z":"54efb553244c241f","name":"","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[],"x":580,"y":1760,"wires":[["6f2aeefec7b0268a"]]},{"id":"9470c79839117bff","type":"function","z":"54efb553244c241f","name":"create cron Schedule","func":"msg.payload = {\n \"command\": \"add\",\n \"name\": \"my dynamic schedule\",\n \"expression\": msg.payload.HourUTC,\n \"expressionType\": \"dates\",\n \"payloadType\": \"default\"\n};\n \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":1760,"wires":[["fb61b81a73fe42ee"]]},{"id":"6f2aeefec7b0268a","type":"debug","z":"54efb553244c241f","name":"debug 23","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":1760,"wires":[]}]

```

In the node's help tab you'll find extensive details for each of the msg properties for the Cron plus node

---

<div class="post-metadata">

**Author:** ![Kimovitzh](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kimovitzh/32/67046_2.png) [@Kimovitzh](https://discourse.nodered.org/u/Kimovitzh)\
**Post date:** [29 August 2022 17:57 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/9 "2022-08-29T17:57:38Z")

</div>

🙌🏻  
That works just beautifully!

Thanks again!

---

<div class="post-metadata">

**Author:** ![Kimovitzh](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kimovitzh/32/67046_2.png) [@Kimovitzh](https://discourse.nodered.org/u/Kimovitzh)\
**Post date:** [9 September 2022 11:01 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/10 "2022-09-09T11:01:34Z")

</div>

Starting to get errors in the setup.  
Shouldn't "msg.payload.records[0];" start with the same as " if ( index \>= 5 &&"

 ![Skærmbillede 2022-09-09 kl. 12.59.36](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/9/2946e8f253b366acd8b7a57ba64912700847dbdb.png)

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [9 September 2022 23:26 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/11 "2022-09-09T23:26:39Z")

</div>

Hello Kim,

yes you are right. I can see now that the code would fail to update to the correct `lowestPrice` since we introduced the hours check with `index`

if we set `lowestPrice` to records[0] and there is no other lowestPrice between the hours 5 to 18 then it would fail to update.

maybe its better to filter out the needed records based on the hours and then check to find the lowest

```auto
// records between hours
let recordsBetween = msg.payload.records.filter((el, index) => index >= 5 && index <= 18);

// start with 1st element
let lowestPrice = recordsBetween[0]

recordsBetween.forEach( el => {
    if ( el.SpotPriceDKK < lowestPrice.SpotPriceDKK) { lowestPrice = el }
})

return { payload: lowestPrice };

```

---

<div class="post-metadata">

**Author:** ![Kimovitzh](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kimovitzh/32/67046_2.png) [@Kimovitzh](https://discourse.nodered.org/u/Kimovitzh)\
**Post date:** [11 September 2022 10:53 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/13 "2022-09-11T10:53:57Z")

</div>

It seems to solve the issue 😌

I tried to introduce a second range, would it be that simple?

```auto
// records between hours
let recordsBetween = msg.payload.records.filter((el, index) => index >= 2 && <= 4 && >= 11 && <= 13);

```

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [11 September 2022 15:04 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/14 "2022-09-11T15:04:07Z")

</div>

hi .. you need `index` infront of some of your code comparisons and maybe also to group with brackets the two separate hour ranges and use OR || ?

```javascript
// records between hours
let recordsBetween = msg.payload.records.filter((el, index) => (index >= 2 && index <= 4) || (index >= 11 && index <= 13));

```

---

<div class="post-metadata">

**Author:** ![Kimovitzh](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kimovitzh/32/67046_2.png) [@Kimovitzh](https://discourse.nodered.org/u/Kimovitzh)\
**Post date:** [11 September 2022 15:50 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/15 "2022-09-11T15:50:10Z")

</div>

> [@UnborN](#):
>
> `let recordsBetween = msg.payload.records.filter((el, index) => (index >= 2 &&`

Tried with the index, but that was with the other one (with the lowestPrice before index)  
Didn't know about the || being OR. 👏🏻

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [25 September 2022 15:50 UTC](https://discourse.nodered.org/t/finding-the-best-energy-price-with-api-call/67070/16 "2022-09-25T15:50:59Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
