Skip to content

Instantly share code, notes, and snippets.

@matz33

matz33/README.md Secret

Created November 24, 2023 15:39
Show Gist options
  • Save matz33/843165d0046cac534864b65e633801a5 to your computer and use it in GitHub Desktop.
Save matz33/843165d0046cac534864b65e633801a5 to your computer and use it in GitHub Desktop.
Get Netatmo Weather station data

Unfortunately the Netatmo node https://github.com/guidone/node-red-contrib-netatmo-dashboard is not working : Nodered crashes 5/6 times a day if you use it. The owner is not willing to maintain his code.

Here is a method to get the Netatmo Data without having to install a module, just using http requests. Here is how it works :

  1. Enter your token and refresh token + client id and client secret in the node Set Netatmo Creds & Tokens. You can use https://flows.nodered.org/node/node-red-contrib-oauth2, or info here https://github.com/guidone/node-red-contrib-netatmo-dashboard#authentication to get it or any other methods

  2. Trigger the inject node Set first info

  3. Then, the inject node Start can be triggered either automatically after a deploy like I configured it (prefered method), or manually if needed

  4. It will get the token, refresh token, and will refresh them after the expiration (returned in the payload by Netatmo) - 5 minutes

  5. If error in getting the token it will retry after 1 hour. You can add any kind of alert (email, etc) after node Delay 1 hour on error to alert you that there is an error and token was not returned (time out etc)

  6. The node Next refresh in... displays the next time the refresh will occur. This one and the associated "delay 1s" can be deleted safely if not needed

  7. The token is stored in the global variable NetatmoAccessToken and is used in the http request after the inject node Get Netatmo Data.

[{"id":"48c9ba7a4d6a5359","type":"http request","z":"dab956b5.a43dd8","name":"Send refresh request","method":"POST","ret":"obj","paytoqs":"ignore","url":"https://api.netatmo.com/oauth2/token","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[{"keyType":"Content-Type","keyValue":"","valueType":"other","valueValue":"application/x-www-form-urlencoded"}],"x":920,"y":1260,"wires":[["1d54981a5bd62dc8"]]},{"id":"493b859e5318d28d","type":"inject","z":"dab956b5.a43dd8","name":"Start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":150,"y":1220,"wires":[["fef4ac6631a48776"]]},{"id":"fef4ac6631a48776","type":"change","z":"dab956b5.a43dd8","name":"Set param request refresh","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"grant_type\":\"refresh_token\",\"refresh_token\":$globalContext(\"NetatmoRefreshToken\"),\"client_id\":$globalContext(\"NetatmoClientId\"),\"client_secret\":$globalContext(\"NetatmoClientSecret\")}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":670,"y":1260,"wires":[["48c9ba7a4d6a5359"]]},{"id":"65f4b6541bc97008","type":"change","z":"dab956b5.a43dd8","name":"Store tokens & delay","rules":[{"t":"set","p":"NetatmoAccessToken","pt":"global","to":"payload.access_token","tot":"msg"},{"t":"set","p":"NetatmoRefreshToken","pt":"global","to":"payload.refresh_token","tot":"msg"},{"t":"set","p":"delay","pt":"msg","to":"payload.expires_in*1000-300000","tot":"jsonata"},{"t":"set","p":"status","pt":"msg","to":"OK","tot":"str"},{"t":"set","p":"NetatmoLastUpdateTime","pt":"global","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":1340,"y":1200,"wires":[["55d78fcc3650ef5c","97c519fc69b9b6e9"]]},{"id":"371e46c1b4744f71","type":"change","z":"dab956b5.a43dd8","name":"Set Netatmo Creds & Tokens","rules":[{"t":"set","p":"NetatmoClientId","pt":"global","to":"Your_client_id","tot":"str"},{"t":"set","p":"NetatmoClientSecret","pt":"global","to":"Your_client_secret","tot":"str"},{"t":"set","p":"NetatmoAccessToken","pt":"global","to":"Your_first_token","tot":"str"},{"t":"set","p":"NetatmoRefreshToken","pt":"global","to":"Your_first_refres_token","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":1180,"wires":[[]]},{"id":"acb161c2964a5538","type":"inject","z":"dab956b5.a43dd8","name":"Set first info","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":1180,"wires":[["371e46c1b4744f71"]]},{"id":"5dd80c83a73ef692","type":"inject","z":"dab956b5.a43dd8","name":"Stop","props":[{"p":"reset","v":"1","vt":"num"},{"p":"status","v":"STOP","vt":"str"},{"p":"delay","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":1300,"wires":[["55d78fcc3650ef5c","97c519fc69b9b6e9","586be2751752f395"]]},{"id":"1d54981a5bd62dc8","type":"switch","z":"dab956b5.a43dd8","name":"All ok ?","property":"payload","propertyType":"msg","rules":[{"t":"hask","v":"access_token","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":1120,"y":1260,"wires":[["65f4b6541bc97008"],["ffd6c9bccc7f0c84"]],"outputLabels":["Response OK","Error"]},{"id":"ffd6c9bccc7f0c84","type":"change","z":"dab956b5.a43dd8","name":"Delay 1 hour on error","rules":[{"t":"set","p":"delay","pt":"msg","to":"3600000","tot":"num"},{"t":"set","p":"status","pt":"msg","to":"KO","tot":"str"},{"t":"set","p":"NetatmoLastUpdateTime","pt":"global","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":1340,"y":1320,"wires":[["55d78fcc3650ef5c","97c519fc69b9b6e9"]]},{"id":"55d78fcc3650ef5c","type":"delay","z":"dab956b5.a43dd8","name":"Refresh","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":460,"y":1260,"wires":[["fef4ac6631a48776"]]},{"id":"97c519fc69b9b6e9","type":"delay","z":"dab956b5.a43dd8","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":460,"y":1320,"wires":[["586be2751752f395"]]},{"id":"586be2751752f395","type":"function","z":"dab956b5.a43dd8","name":"Next refresh in...","func":"var d = new Date();\nvar n = d.getTime();\nvar start_time = global.get('NetatmoLastUpdateTime')||0;\nvar duration = msg.delay/1000;\nvar elapsed_time = Math.round((n - start_time)/1000);\n\nvar remains = new Date(null);\nremains.setSeconds(duration - elapsed_time); // specify value for SECONDS here\nvar remains_h = remains.toISOString().substr(11, 8);\nif (msg.status == \"STOP\") {\n node.status({});\n msg.remains = \"00:00:00\";\n msg.payload = 0;\n return [null, msg];\n}\nif (elapsed_time < duration) {\n node.status({fill:msg.status == \"OK\" ? \"blue\" : \"red\",shape:\"dot\", text:remains_h});\n msg.remains = remains_h;\n return [ msg, null ];\n}\n\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":1380,"wires":[["97c519fc69b9b6e9"],[]]},{"id":"944f8def659f9d52","type":"change","z":"dab956b5.a43dd8","name":"","rules":[{"t":"set","p":"token","pt":"msg","to":"\"Bearer \" & $globalContext(\"NetatmoAccessToken\")\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":1460,"wires":[["b96f28348953dfca"]]},{"id":"b96f28348953dfca","type":"http request","z":"dab956b5.a43dd8","name":"Netatmo Https","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.netatmo.com/api/getstationsdata","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[{"keyType":"other","keyValue":"Authorization","valueType":"msg","valueValue":"token"}],"x":680,"y":1460,"wires":[["7df73f6e51fbc4a5"]]},{"id":"7f8ab2a7eb362ac8","type":"inject","z":"dab956b5.a43dd8","name":"Get Netatmo Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":110,"y":1460,"wires":[["944f8def659f9d52"]]},{"id":"7df73f6e51fbc4a5","type":"debug","z":"dab956b5.a43dd8","name":"Netatmo Data","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":900,"y":1460,"wires":[]}]
@morpheus1984
Copy link

@jostrasser Mhh, i copied the complete flow and added my different tokens. So i think i cant do so much wrong. 🤷🏼 Do i need the additional Oauth2 nodes to get the tokens? Until now i just used the Flow i copied from here

@jostrasser
Copy link

@jostrasser Mhh, i copied the complete flow and added my different tokens. So i think i cant do so much wrong. 🤷🏼 Do i need the additional Oauth2 nodes to get the tokens? Until now i just used the Flow i copied from here

No, this flow and a fresh token pair should be enough. And you are always getting a „Access token is missing“?

@morpheus1984
Copy link

@jostrasser checked all again, got new tokens from Netatmo, always same error. Is there something special when working with variables? I don't do that for other things in node red right now.

13.6.2024, 21:13:55node: Netatmo Data
msg : Object
object
payload: object
error: object
code: 1
message: "Access token is missing"
topic: ""
_msgid: "a28c1e48.a4dee"
token: "Bearer 5656ab5465d1c471498b463a|e7344516a7ffbb99XXXXXXXXXXXX"
statusCode: 400
headers: object
responseUrl: "https://api.netatmo.com/api/getstationsdata"
redirectList: array[0]

Thanks for helping.

@mhin76
Copy link

mhin76 commented Jun 14, 2024

Update: it all works fine with the original code provided above. I used another oauth2 node called node-red-contrib-oauth2. that does not work. somehow it generates another refresh and access token pair (not sure how that is even possible) and that fails after a while.
I was in contact with a Netatmo supporter, he told me that they deactivated recently the usage of parallel token pair usage. Now only one pair will be valid, all others invalid. That is why this method worked before but now not anymore.
so all fine on my side :) happy with the code provide. thanks @matz33

@S474N
Copy link

S474N commented Jun 20, 2024

Again problem with token:
image
Tested regenerating token, but it doesn't solve the problem.

@kailausberg
Copy link

Not here... works flawless.

@jostrasser
Copy link

Same here,... I also restarted the whole Node-Red installation (because I updated to Node-Red 4.0). All is working flawless.

@S474N
Copy link

S474N commented Jun 21, 2024

Again regenerated tokens and it change also first two credetinals. Seems to be ok.

@PADIGITHUB1
Copy link

i have the same problem as @morpheus1984 "Access token is missing"... do i need to update Node-RED ?

@kailausberg
Copy link

i have the same problem as @morpheus1984 "Access token is missing"... do i need to update Node-RED ?

yes - you should!

@martiko70
Copy link

In general, the flow is really working fine. For approx. 5-7 days. Then the token(s) are no longer accepted and I have to recreate the initial Access and Refresh Token. After entering them in the "Set Netatmo Creds & Tokens" node, it works again... for nearly one week, and I have to start agein.
Any idea, why it stopps working after a certain time? And even better... an idea how to make the flow more stable?

@matz33
Copy link
Author

matz33 commented Jul 14, 2024

Are you sure that the error you get is because the tokens are no longer accepted ? Maybe your node-red restarts and lose the tokens stored in the variables ? Have you enabled the option to store variable on disk like explained here https://gist.github.com/matz33/843165d0046cac534864b65e633801a5?permalink_comment_id=4785976#gistcomment-4785976 ?

@martiko70
Copy link

@matz33
Thanks for the hint, I will give this a try.
First I tried to enter the proposes settings
contextStorage: { default: { module:"localfilesystem", config: { dir:"/data", base:"context", cache: true, flushInterval: 30 } }, },

But then, nodered did not start anymore... :-( As I am not so experienced, I only removed the comments from the already existing entry, so I have only:
contextStorage: { default: { module:"localfilesystem" }, },

I hope this is sufficient an will check if it is working stable for a longer time now.

Thanks again!

@FlorianDessloch
Copy link

@matz33 Thanks for the hint, I will give this a try. First I tried to enter the proposes settings contextStorage: { default: { module:"localfilesystem", config: { dir:"/data", base:"context", cache: true, flushInterval: 30 } }, },

But then, nodered did not start anymore... :-( As I am not so experienced, I only removed the comments from the already existing entry, so I have only: contextStorage: { default: { module:"localfilesystem" }, },

I hope this is sufficient an will check if it is working stable for a longer time now.

Thanks again!

I have an environment running using the exact same config.

Why don't you just test ist?
Check if the tokens are there, using the context tab.
Restart nodered, check again and if they are gone it's not set up or working correctly.

@msommerx
Copy link

I'm running node red 4.0.2 on Debian.
I configured everything correctly (think so), including saving the credentials locally (global.json contains credentials) but node red gives me an error after clicking on start "RequestError: The "listener" argument must be of type function. Received an instance of Object".
Anybody knows what's the problem?

@mkninc
Copy link

mkninc commented Jul 26, 2024

I've the same problems .
The access token is only accepted once. In subsequent accesses the token is not accepted. I get 'message: "Invalid access token"'.

@matthiasbaldi
Copy link

For me that works, but remember the first flow is only to trigger the hole thing once (do not repeat). And then in the following requests the second flow is refreshing the access token, so older access tokens get invalid.
This is why he saves the access token in a global (or flow) variable and then overwrites it in the second flow.

@mrmaximas
Copy link

mrmaximas commented Jul 26, 2024

Sure. This flow works good for six months for me, like swiss clock, with the local keys storage.

@martiko70
Copy link

After having added the local storage, I had no further problems. So obviously the flow was restartet (why so ever) which caused a loss of the keys. Now it's already up and running for two weeks without any problems.

@mkninc
Copy link

mkninc commented Jul 26, 2024

My fault. I had set an interval in the "Set first info" node. For whatever reason. 🤦‍♂️
It's working now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment