Personal Weather Station data import using Node Red

I have a “Pantech WH2900” personal weather station, which seems like it’s a white-labelled variant of a Ambient WS-2902 - https://www.ambientweather.com/amws2902.html

I’ve been struggling to get the data integrated into Home Assistant using weewx and intercept drivers, until I decided to use Node-Red.

I created a http endpoint in Node-Red which receives the data using the ecowitt protocol, configured like this in the app…

Then I need to do some unit conversions, and output to home assistant sensors.

I’ve obviously tested only with my PWS, but I assume the same flow should work with any PWS that can use the ecowitt protocol to send data to a custom server.

Here is the node-red code if anyone wants to give it a go…

[{"id":"c2802b40.2b07c8","type":"tab","label":"Weather Station","disabled":false,"info":""},{"id":"4a568252.a4270c","type":"http response","z":"c2802b40.2b07c8","name":"","statusCode":"","headers":{},"x":130,"y":260,"wires":[]},{"id":"188ceb1c.321dc5","type":"http in","z":"c2802b40.2b07c8","name":"Incoming Weather Data","url":"/weather","method":"post","upload":false,"swaggerDoc":"","x":180,"y":360,"wires":[["4a568252.a4270c","e197a1a.a0dc56","df151c2c.c6ecc","f97d2572.9a97b8","137d29d3.4f6446","97e472bf.f372a","246154bc.fd06fc","65c3eecd.8cf2e","dbf42355.57edd","ccfd1178.f17dd","c00f531a.63299"]]},{"id":"e197a1a.a0dc56","type":"ha-entity","z":"c2802b40.2b07c8","name":"Wind Direction","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Wind Direction"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:compass"},{"property":"unit_of_measurement","value":"°"}],"state":"payload.winddir","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":440,"y":40,"wires":[[]]},{"id":"df151c2c.c6ecc","type":"ha-entity","z":"c2802b40.2b07c8","name":"Humidity","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Weather Station Humidity"},{"property":"device_class","value":"humidity"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"%"}],"state":"payload.humidity","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":420,"y":100,"wires":[[]]},{"id":"f97d2572.9a97b8","type":"unit-converter","z":"c2802b40.2b07c8","category":"temperature","inputUnit":"F","outputUnit":"C","inputField":"payload.tempf","outputField":"payload","inputFieldType":"msg","outputFieldType":"msg","name":"F to C","x":410,"y":160,"wires":[["173a30c1.b5b3bf"]]},{"id":"8432e3bb.fb241","type":"ha-entity","z":"c2802b40.2b07c8","name":"Temperature","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Weather Station Temperature"},{"property":"device_class","value":"temperature"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"°C"}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":850,"y":160,"wires":[[]]},{"id":"137d29d3.4f6446","type":"unit-converter","z":"c2802b40.2b07c8","category":"speed","inputUnit":"m/h","outputUnit":"km/h","inputField":"payload.windspeedmph","outputField":"payload","inputFieldType":"msg","outputFieldType":"msg","name":"mph to kmph","x":440,"y":220,"wires":[["9d95ca4c.03a6e8"]]},{"id":"b969287b.198cb8","type":"ha-entity","z":"c2802b40.2b07c8","name":"Wind Speed","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Wind Speed"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:weather-windy"},{"property":"unit_of_measurement","value":"km/h"}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":850,"y":220,"wires":[[]]},{"id":"97e472bf.f372a","type":"unit-converter","z":"c2802b40.2b07c8","category":"speed","inputUnit":"m/h","outputUnit":"km/h","inputField":"payload.windgustmph","outputField":"payload","inputFieldType":"msg","outputFieldType":"msg","name":"mph to kmph","x":440,"y":280,"wires":[["e8e92d12.8e85e"]]},{"id":"777c4951.f99c88","type":"ha-entity","z":"c2802b40.2b07c8","name":"Wind Gust","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Wind Gust"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:weather-tornado"},{"property":"unit_of_measurement","value":"km/h"}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":850,"y":280,"wires":[[]]},{"id":"246154bc.fd06fc","type":"unit-converter","z":"c2802b40.2b07c8","category":"length","inputUnit":"in","outputUnit":"mm","inputField":"payload.rainratein","outputField":"payload","inputFieldType":"msg","outputFieldType":"msg","name":"\" to mm","x":420,"y":340,"wires":[["3efd90f4.3e62b","114566c9.6230b9"]]},{"id":"b6951c41.319fe","type":"ha-entity","z":"c2802b40.2b07c8","name":"Rain Rate","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Rain Rate"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:weather-rainy"},{"property":"unit_of_measurement","value":"mm/hr"}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":840,"y":340,"wires":[[]]},{"id":"65c3eecd.8cf2e","type":"unit-converter","z":"c2802b40.2b07c8","category":"length","inputUnit":"in","outputUnit":"mm","inputField":"payload.dailyrainin","outputField":"payload","inputFieldType":"msg","outputFieldType":"msg","name":"\" to mm","x":420,"y":460,"wires":[["5438955b.d50c0c"]]},{"id":"3922801c.04aea","type":"ha-entity","z":"c2802b40.2b07c8","name":"Rain Accumulation","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Rain Accumulation"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:cup-water"},{"property":"unit_of_measurement","value":"mm"}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":870,"y":460,"wires":[[]]},{"id":"b22429c6.87f798","type":"ha-entity","z":"c2802b40.2b07c8","name":"Raining","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"binary_sensor","config":[{"property":"name","value":"Raining"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:weather-pouring"},{"property":"unit_of_measurement","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":840,"y":400,"wires":[[]]},{"id":"dbf42355.57edd","type":"function","z":"c2802b40.2b07c8","name":"Pressure","func":"var baromabsin = Number(msg.payload.baromabsin)\nvar pressure = baromabsin * 33.863886666667\n\nmsg.payload = pressure.toFixed(1)\nreturn msg;","outputs":1,"noerr":0,"x":420,"y":540,"wires":[["80930617.f29d98"]]},{"id":"80930617.f29d98","type":"ha-entity","z":"c2802b40.2b07c8","name":"Atmospheric Pressure","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Atmospheric Pressure"},{"property":"device_class","value":"pressure"},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"hPa"}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":660,"y":540,"wires":[[]]},{"id":"ccfd1178.f17dd","type":"function","z":"c2802b40.2b07c8","name":"Solar Radiation","func":"var x = Number(msg.payload.solarradiation)\nmsg.payload = x.toFixed(1)\nreturn msg;","outputs":1,"noerr":0,"x":440,"y":620,"wires":[["99944557.d4dbc8"]]},{"id":"99944557.d4dbc8","type":"ha-entity","z":"c2802b40.2b07c8","name":"Solar Radiation","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Solar Radiation"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:white-balance-sunny"},{"property":"unit_of_measurement","value":"W/m²"}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":640,"y":620,"wires":[[]]},{"id":"c00f531a.63299","type":"ha-entity","z":"c2802b40.2b07c8","name":"UV","server":"a23a4d01.eeb32","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"UV"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:weather-sunny-alert"},{"property":"unit_of_measurement","value":""}],"state":"payload.uv","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":410,"y":700,"wires":[[]]},{"id":"3efd90f4.3e62b","type":"function","z":"c2802b40.2b07c8","name":"raining?","func":"var x = Number(msg.payload)\n\nif (x > 0) {\n   msg.payload = true;\n} else {\n   msg.payload = false;\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":620,"y":400,"wires":[["b22429c6.87f798"]]},{"id":"173a30c1.b5b3bf","type":"function","z":"c2802b40.2b07c8","name":"Single Decimal Place","func":"var x = Number(msg.payload)\n\nmsg.payload = x.toFixed(1)\nreturn msg;","outputs":1,"noerr":0,"x":660,"y":160,"wires":[["8432e3bb.fb241"]]},{"id":"9d95ca4c.03a6e8","type":"function","z":"c2802b40.2b07c8","name":"Single Decimal Place","func":"var x = Number(msg.payload)\n\nmsg.payload = x.toFixed(1)\nreturn msg;","outputs":1,"noerr":0,"x":660,"y":220,"wires":[["b969287b.198cb8"]]},{"id":"e8e92d12.8e85e","type":"function","z":"c2802b40.2b07c8","name":"Single Decimal Place","func":"var x = Number(msg.payload)\n\nmsg.payload = x.toFixed(1)\nreturn msg;","outputs":1,"noerr":0,"x":660,"y":280,"wires":[["777c4951.f99c88"]]},{"id":"114566c9.6230b9","type":"function","z":"c2802b40.2b07c8","name":"Single Decimal Place","func":"var x = Number(msg.payload)\n\nmsg.payload = x.toFixed(1)\nreturn msg;","outputs":1,"noerr":0,"x":660,"y":340,"wires":[["b6951c41.319fe"]]},{"id":"5438955b.d50c0c","type":"function","z":"c2802b40.2b07c8","name":"Single Decimal Place","func":"var x = Number(msg.payload)\n\nmsg.payload = x.toFixed(1)\nreturn msg;","outputs":1,"noerr":0,"x":660,"y":460,"wires":[["3922801c.04aea"]]},{"id":"a23a4d01.eeb32","type":"server","z":"","name":"Home Assistant"}]
2 Likes

Hey this is a nice solution if it works for other people as well. Good work.

Have you any thoughts on how the same method could work without Node Red in HA ?
I don’t use Node Red (yet) and I run HA on hassOS on an RPi.
Wondering if there is a component to create a server in HA itself that the station can upload the data to.

Hi @mr.sneezy - yeah that sounds about right (i think)

Truth be told I have no idea how to write code or how to create a native HA integration. This is why I have (recently) gotten into Node Red. It’s like coding for people who don’t know how to code! :slight_smile:

I know how to code and I prefer Node Red for my automations.

1 Like

Yeah, I’m probably going to have to try it (Node Red). Been reluctant because I’d already spent two years learning to learn HA (i.e. YAML, scripting etc) but I can see it’s a nice thing. How steep is the learning curve compared to HA automations ?

BTW, I also have the Pantech WH2900, and very happy with it.

I’m only getting started with it as well, so can only really speak from my experience, but I’ve found that just like with HA automations, once I got my head around the basic concepts things got a little quicker. Best way I think is to just play around a bit. The hassio addin is a good starting point as it already has the HA nodes all integrated. There’s also a HACS node-red integration which is worth getting because this is what allows you to easily create sensors in HA. My weather-station flow above, relies on having that ability.

Agreed, the Pantech weather station seems pretty good to me too. Nice to finally now also have the data in HA so I can start to do things like control my aircon based on the weather.

Hi, I’ve installed Node-Red now and am getting the hang of it slowly. Some stuff is a little obscure to me but every coding method has some of that.
Two quick questions. Have you updated your flow at all in the last few months, if so would you repost it so I can try out your latest ?
And you mentioned the HACS Node-Red integration above, is that required to be able to use your NR flow ?
Cheers, Martin.

Hi Martin,
Nope not updated it - that should work. But yes you will need the HACS Node-Red integration because the flow creates sensors in Home Assistant for all the values reported by the weather station, and in order to do that, the integration is used.

Found something interesting in the link below, a plugin for Domoticz that directly converts data from the WH2900 and similar stations. I wonder if that’s possible in HA as well ?

https://www.domoticz.com/forum/viewtopic.php?t=29327

This is exactly what I’m looking for… Unfortunately, I cant seem to get it to work. I have an Ecowitt gw1000 gateway, which is setup like your app is setup. I have copied your node red code installed the missing components, deployed, and I don’t get any data in. Is there something I’m missing?

Hi gameover,
you have to use the exact same http endpoint name in both nodered and the ecowitt server. The provided nodered import uses ‚/weather‘, whereas the picture shows ‚/endpoint/weather‘.
Hope this helps.

1 Like

@gameover did you ever get this to work?

I have just spent a couple of days getting my GW1000 to work and there were some caveats not mentioned in this post, mostly to do with SSL and authentication.

Hi Damps! this looks exacly like what I am looking for! However I tried to install it and just get nothing. I could import the flow, and when I deploy it, I get a message sayind “disconected” under each entity node. I am quite new to hass and node-red, so I couldnt even figure out a way to see where the problem lies (are the data sent to the right place ? How do I make sure that the server listens on the right port ?) Thanks for any help!

I looked all over that site and cant figure out how that software (weewx) get’s the data.
do you need some sort of external rf dongle to listen in? or does it scrape your weather host/controller for the data?

I know that this post is older but I got an ecowitt weather station and I followed a guide on how to get it into HA. It seems that the ECOWITT integration is no longer configured in the UI. But I got it to work using the node red flow above. It works fine for some sensors. Obviously if your model doesn’t have those sensors it will not work. But the ones that do are having errors. I have rain and humidity to work. But the debug on temperature and the other sensors that are supported say “NaN”. Did you experience this?

I was having periodic NaN issues with some sensors (mostly wind direction, gust, etc.) with this Node-RED approach.

After some research, I tried using ecowitt2mqtt instead and it is performing flawlessly. (I took the simple way out an just pulled down the Docker image.)

I’m not sure why this works better than Node-RED for me, but maybe there’s something flaky about HTTP endpoints in NR+HA.

hi,
leider funktioniert der upload bei mir nicht.
wie kann ich testen ob überhaupt was hochgeladen wird?
lg Jörn