ottopaulsen / node-red-contrib-power-saver

A Node-RED node to saver money by turning off when the power is most expensive
Other
71 stars 17 forks source link

[Request for new functionality] Read data directly from Nord Pool API node? #40

Closed houser42 closed 2 years ago

houser42 commented 2 years ago

Hello. I am trying to use this seemingly great package just in node red with either one of the two nordpool api nodes: node-red-contrib-nordpool-api or node-red-contrib-nordpool-api-plus. Maybe I am missing something and it can already be done?

The nordpool api nodes output respectively 24 or 48 hourly pricing as an array that is very similar but not the same as the format required by this node-red-contrib-power-saver. Example sample as starting point if you have not looked at it:

object
payload: array[48]
[0 … 9]
0: object
Area: "SE3"
Timestamp: "2022-02-17 00:00"
StartTime: "2022-02-17 00:00"
EndTime: "2022-02-17 01:00"
Price: 184.82
Valuta: "SEK/MWh"

Or perhaps find a way to do this in a function node to convert the output from Nord Pool API to the common strategy input format. Can you comment or suggest best practice for this please? Many thanks!

ottopaulsen commented 2 years ago

Hi, good to see someone using this without Home Assistant too. I did try those nodes some time ago, but found that they had some flaws, so I focused on other sources for price. However, if they give you data, it should be possible to use them. The best solution for now would be to send data through a function node and convert to the common strategy input format, as you suggest. That is a fairly easy job if you know how to work with arrays in JavaScript.

houser42 commented 2 years ago

Thanks @ottopaulsen

Reply much appreciated! Any chance of a hint to get me started? A function node example somewhere? I have searched without any success for a good starting point as I am afraid I am not a master of javascript. Ah well. Thanks again regardless! Here is the complete array from the node I am using if some one has the time to take a peek. It has 48 timestamped prices so shows today and tomorrow., so useful. From https://github.com/Csstenersen/node-red-contrib-nordpool-api

{"payload":[{"Area":"SE3","Timestamp":"2022-02-18 00:00","StartTime":"2022-02-18 00:00","EndTime":"2022-02-18 01:00","Price":140.26,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 01:00","StartTime":"2022-02-18 01:00","EndTime":"2022-02-18 02:00","Price":135.49,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 02:00","StartTime":"2022-02-18 02:00","EndTime":"2022-02-18 03:00","Price":135.07,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 03:00","StartTime":"2022-02-18 03:00","EndTime":"2022-02-18 04:00","Price":135.49,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 04:00","StartTime":"2022-02-18 04:00","EndTime":"2022-02-18 05:00","Price":139.41,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 05:00","StartTime":"2022-02-18 05:00","EndTime":"2022-02-18 06:00","Price":143.12,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 06:00","StartTime":"2022-02-18 06:00","EndTime":"2022-02-18 07:00","Price":286.35,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 07:00","StartTime":"2022-02-18 07:00","EndTime":"2022-02-18 08:00","Price":1016.99,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 08:00","StartTime":"2022-02-18 08:00","EndTime":"2022-02-18 09:00","Price":1057.77,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 09:00","StartTime":"2022-02-18 09:00","EndTime":"2022-02-18 10:00","Price":1109.36,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 10:00","StartTime":"2022-02-18 10:00","EndTime":"2022-02-18 11:00","Price":1014.87,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 11:00","StartTime":"2022-02-18 11:00","EndTime":"2022-02-18 12:00","Price":954.38,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 12:00","StartTime":"2022-02-18 12:00","EndTime":"2022-02-18 13:00","Price":986.9,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 13:00","StartTime":"2022-02-18 13:00","EndTime":"2022-02-18 14:00","Price":835.94,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 14:00","StartTime":"2022-02-18 14:00","EndTime":"2022-02-18 15:00","Price":715.39,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 15:00","StartTime":"2022-02-18 15:00","EndTime":"2022-02-18 16:00","Price":794.84,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 16:00","StartTime":"2022-02-18 16:00","EndTime":"2022-02-18 17:00","Price":1007.24,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 17:00","StartTime":"2022-02-18 17:00","EndTime":"2022-02-18 18:00","Price":1205.98,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 18:00","StartTime":"2022-02-18 18:00","EndTime":"2022-02-18 19:00","Price":1250.79,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 19:00","StartTime":"2022-02-18 19:00","EndTime":"2022-02-18 20:00","Price":1231.3,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 20:00","StartTime":"2022-02-18 20:00","EndTime":"2022-02-18 21:00","Price":1164.98,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 21:00","StartTime":"2022-02-18 21:00","EndTime":"2022-02-18 22:00","Price":1134.68,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 22:00","StartTime":"2022-02-18 22:00","EndTime":"2022-02-18 23:00","Price":1052.9,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-18 23:00","StartTime":"2022-02-18 23:00","EndTime":"2022-02-19 00:00","Price":915.29,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 00:00","StartTime":"2022-02-19 00:00","EndTime":"2022-02-19 01:00","Price":265.48,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 01:00","StartTime":"2022-02-19 01:00","EndTime":"2022-02-19 02:00","Price":264.63,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 02:00","StartTime":"2022-02-19 02:00","EndTime":"2022-02-19 03:00","Price":175.96,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 03:00","StartTime":"2022-02-19 03:00","EndTime":"2022-02-19 04:00","Price":152.16,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 04:00","StartTime":"2022-02-19 04:00","EndTime":"2022-02-19 05:00","Price":136.92,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 05:00","StartTime":"2022-02-19 05:00","EndTime":"2022-02-19 06:00","Price":138.19,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 06:00","StartTime":"2022-02-19 06:00","EndTime":"2022-02-19 07:00","Price":138.82,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 07:00","StartTime":"2022-02-19 07:00","EndTime":"2022-02-19 08:00","Price":139.99,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 08:00","StartTime":"2022-02-19 08:00","EndTime":"2022-02-19 09:00","Price":145.07,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 09:00","StartTime":"2022-02-19 09:00","EndTime":"2022-02-19 10:00","Price":154.7,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 10:00","StartTime":"2022-02-19 10:00","EndTime":"2022-02-19 11:00","Price":164.22,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 11:00","StartTime":"2022-02-19 11:00","EndTime":"2022-02-19 12:00","Price":165.17,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 12:00","StartTime":"2022-02-19 12:00","EndTime":"2022-02-19 13:00","Price":168.87,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 13:00","StartTime":"2022-02-19 13:00","EndTime":"2022-02-19 14:00","Price":161.79,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 14:00","StartTime":"2022-02-19 14:00","EndTime":"2022-02-19 15:00","Price":151.2,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 15:00","StartTime":"2022-02-19 15:00","EndTime":"2022-02-19 16:00","Price":146.23,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 16:00","StartTime":"2022-02-19 16:00","EndTime":"2022-02-19 17:00","Price":166.02,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 17:00","StartTime":"2022-02-19 17:00","EndTime":"2022-02-19 18:00","Price":1057.58,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 18:00","StartTime":"2022-02-19 18:00","EndTime":"2022-02-19 19:00","Price":1213.55,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 19:00","StartTime":"2022-02-19 19:00","EndTime":"2022-02-19 20:00","Price":1159.69,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 20:00","StartTime":"2022-02-19 20:00","EndTime":"2022-02-19 21:00","Price":1005.84,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 21:00","StartTime":"2022-02-19 21:00","EndTime":"2022-02-19 22:00","Price":1013.35,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 22:00","StartTime":"2022-02-19 22:00","EndTime":"2022-02-19 23:00","Price":970.82,"Valuta":"SEK/MWh"},{"Area":"SE3","Timestamp":"2022-02-19 23:00","StartTime":"2022-02-19 23:00","EndTime":"2022-02-20 00:00","Price":712.11,"Valuta":"SEK/MWh"}],"topic":"hourly","_msgid":"9276b032c8384750"}

ottopaulsen commented 2 years ago

A function node with this code would do:

const priceData = msg.payload.map(h => {
    const date = h.StartTime.substring(0, 10)
    const hour = h.StartTime.substring(11, 16)
    return {
        value: h.Price / 1000.0,
        start: date + "T" + hour + ":00.000+01:00"
    }
})
return {payload: {priceData, source: "Other" }};

Send the prices in and send the output to the strategy node. This will only work until DST is change from winter to rummer time. Then the +01:00 must be changed to +02:00. Of course, a date conversion that takes care of that would be better.

houser42 commented 2 years ago

Dear @ottopaulsen

Deeply impressed! That just seems to work off the bat. So grateful! I will get back with some form of a report on how this works in plain node red. Will study your website and see how far I can use this n my config. Many thanks and have a great weekend!

houser42 commented 2 years ago

Just confirming that this works as expected. Many thanks again! For planning purposes I would finally like to put the strategy schedule into a chart with the same timeline as the strategy price chart, so that consequences of programming becomes clear. Could you tell me how to use a function to format the schedule object part from the strategy nodes in to a node red chart? Maybe someone has already done this? Attached is a the chart for the price itself to make it clear. Many thanks for any hints or starting point flow examples

Screenshot 2022-02-21 at 09 04 26

.

ottopaulsen commented 2 years ago

Sorry, I haven't used Node-RED charts. Looks nice.

houser42 commented 2 years ago

Thanks for the reply @ottopaulsen regardless;) I'll continue the experiment. Slowly but surely getting there I hope ;)

houser42 commented 1 year ago

Hello again. Your code has been working great since it was setup. Very useful and many thanks again for that!

A follow up question if that is allowed? It would also be nice with a way to request what the price is right now as well as highest and lowest price during a day. Many thanks regardless!

ottopaulsen commented 1 year ago

These are good ideas, thanks. I will keep them in mind.

houser42 commented 1 year ago

Many thanks for your kind reply. I have some nice code for a general function node, so good for now..

calania commented 1 year ago

Hello! I am also not using home assistant but want to get this node working. I tried the script @ottopaulsen made but am getting the following error in my function node

"TypeError: Cannot read properties of undefined (reading 'substring')"

Any ideas why this might be?

This was the flow I tested it with

[ { "id": "8f6ffcd899d215a7", "type": "nordpool-api-plus", "z": "a93551d4.0ad2e8", "name": "", "area": "SE4", "currency": "SEK", "action": "dayAhead", "x": 340, "y": 2280, "wires": [ [ "d9dc90b9eccf61ad" ] ] }, { "id": "60047b6f9acd1643", "type": "inject", "z": "a93551d4.0ad2e8", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 180, "y": 2280, "wires": [ [ "8f6ffcd899d215a7" ] ] }, { "id": "d9dc90b9eccf61ad", "type": "function", "z": "a93551d4.0ad2e8", "name": "function 1", "func": "const priceData = msg.payload.map(h => {\n const date = h.StartTime.substring(0, 10)\n const hour = h.StartTime.substring(11, 16)\n return {\n value: h.Price / 1000.0,\n start: date + \"T\" + hour + \":00.000+01:00\"\n }\n})\nreturn { payload: { priceData, source: \"Other\" } };", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 520, "y": 2280, "wires": [ [ "a4760ae2a0ed552e" ] ] }, { "id": "a4760ae2a0ed552e", "type": "ps-receive-price", "z": "a93551d4.0ad2e8", "name": "Price Receiver", "x": 680, "y": 2280, "wires": [ [] ] } ]

ottopaulsen commented 1 year ago

The error message you are getting means that StartTime is not found where expected, so you must check the data you send in to the node.

calania commented 1 year ago

Yea it seems that you are right. This is the output for me from the nordpool node

[{"timestamp":"2023-01-28T23:00:00.000Z","price":334.98,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T00:00:00.000Z","price":330.03,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T01:00:00.000Z","price":319.34,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T02:00:00.000Z","price":317.76,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T03:00:00.000Z","price":322.15,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T04:00:00.000Z","price":303.8,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T05:00:00.000Z","price":306.84,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T06:00:00.000Z","price":328.46,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T07:00:00.000Z","price":347.82,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T08:00:00.000Z","price":352.43,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T09:00:00.000Z","price":386.76,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T10:00:00.000Z","price":382.71,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T11:00:00.000Z","price":381.47,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T12:00:00.000Z","price":393.4,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T13:00:00.000Z","price":386.99,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T14:00:00.000Z","price":366.28,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T15:00:00.000Z","price":390.48,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T16:00:00.000Z","price":412.54,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T17:00:00.000Z","price":392.28,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T18:00:00.000Z","price":350.86,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T19:00:00.000Z","price":321.14,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T20:00:00.000Z","price":292.44,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T21:00:00.000Z","price":282.31,"currency":"SEK","area":"SE4"},{"timestamp":"2023-01-29T22:00:00.000Z","price":206.44,"currency":"SEK","area":"SE4"}]

Will have to see if I can modify your script to make it work

calania commented 1 year ago

I have modified the function node and am now getting the following output from the function node

{"priceData":[{"value":0.33498,"start":"2023-01-28T23:00:00.000+01:00"},{"value":0.33003,"start":"2023-01-29T00:00:00.000+01:00"},{"value":0.31933999999999996,"start":"2023-01-29T01:00:00.000+01:00"},{"value":0.31776,"start":"2023-01-29T02:00:00.000+01:00"},{"value":0.32215,"start":"2023-01-29T03:00:00.000+01:00"},{"value":0.3038,"start":"2023-01-29T04:00:00.000+01:00"},{"value":0.30684,"start":"2023-01-29T05:00:00.000+01:00"},{"value":0.32846,"start":"2023-01-29T06:00:00.000+01:00"},{"value":0.34782,"start":"2023-01-29T07:00:00.000+01:00"},{"value":0.35243,"start":"2023-01-29T08:00:00.000+01:00"},{"value":0.38676,"start":"2023-01-29T09:00:00.000+01:00"},{"value":0.38271,"start":"2023-01-29T10:00:00.000+01:00"},{"value":0.38147000000000003,"start":"2023-01-29T11:00:00.000+01:00"},{"value":0.39339999999999997,"start":"2023-01-29T12:00:00.000+01:00"},{"value":0.38699,"start":"2023-01-29T13:00:00.000+01:00"},{"value":0.36628,"start":"2023-01-29T14:00:00.000+01:00"},{"value":0.39048,"start":"2023-01-29T15:00:00.000+01:00"},{"value":0.41254,"start":"2023-01-29T16:00:00.000+01:00"},{"value":0.39227999999999996,"start":"2023-01-29T17:00:00.000+01:00"},{"value":0.35086,"start":"2023-01-29T18:00:00.000+01:00"},{"value":0.32114,"start":"2023-01-29T19:00:00.000+01:00"},{"value":0.29244,"start":"2023-01-29T20:00:00.000+01:00"},{"value":0.28231,"start":"2023-01-29T21:00:00.000+01:00"},{"value":0.20643999999999998,"start":"2023-01-29T22:00:00.000+01:00"}],"source":"Other"}

But when I send that data into the price receiver node I get the following error

TypeError: Cannot destructure property 'priceData' of 'getPriceData(...)' as it is null.

Any idea what might be wrong with the payload?

ottopaulsen commented 1 year ago

Yes, now you already have the format that the strategy nodes need, so you can skip the price receiver node.