Shelly WS90 Weather Station

I have a Shelly WS90 weather station correctly paired with the Shelly app through a Shelly BLU dongle. The device works as expected inside the Shelly app, and the BLU dongle is also detected correctly by Home Assistant.

However, the WS90 itself is not discovered by Home Assistant at all.

My understanding is that the BLU dongle forwards BLE data only to the Shelly Cloud/App, and does not expose WS90 sensor data through the local API or via the standard Shelly integration in Home Assistant.

Before I proceed with alternative solutions (MQTT gateway, custom BLE integration, etc.), I would like to confirm whether the WS90 is currently supposed to be discoverable by Home Assistant when connected through a Shelly BLU dongle, or if this is a known limitation.

Thanks for any clarification.

I don’t know how it acts when shelly resells it, but I have the straight up Ecowitt version with their RF and I get all the things.

Do you have an ESP32 Bluetooth proxy? I have several other Shelly BLU devices working well that way. An ESP32 board costs like $4 so might as well test.

I have a spare esp board. Do I have to config as a simple Bluetooth proxy or something else?

Yes, basic Bluetooth proxy should do it.

My neighbor got a Shelly WS90. I picked it up in my Home Assistant installation using the built in bluetooth. I could see all sensors, be it intermittently due to the range limit. So adding a bluetooth proxy is a good idea.

That’s the reply from Shelly Support:
“Thank you for your feedback!
You should configure it as a zigbee device in home assistant in order to work”

Solved positioning an esp32 bluetooth proxy in range and added with BTHome.

Now I can see sensors but, for example, direction is see as degrees…

Yes, that is the way the WS90 works. This is also the case if you have an Ecowitt basestation. You can solve this with a template sensor.

{% if states("sensor.gw2000a_wind_direction")|float(default=0.0) < 23 %}
  N
{% elif states("sensor.gw2000a_wind_direction")|float(default=0.0) < 68 %}
  NO
{% elif states("sensor.gw2000a_wind_direction")|float(default=0.0) < 113 %}
  O
{% elif states("sensor.gw2000a_wind_direction")|float(default=0.0) < 158 %}
  ZO
{% elif states("sensor.gw2000a_wind_direction")|float(default=0.0) < 203 %}
  Z
{% elif states("sensor.gw2000a_wind_direction")|float(default=0.0) < 248 %}
  ZW
{% elif states("sensor.gw2000a_wind_direction")|float(default=0.0) < 293 %}
  W
{% elif states("sensor.gw2000a_wind_direction")|float(default=0.0) < 338 %}
  NW
{% else %}
  N
{% endif %}

A bit shorter code would be something like below showing NNE as well but this can be changed by dividing by 45 and remove the 3 character winddirections to get only NE. It’s using an array for with the index calculated from the degrees.

{% set directions = [ 'N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N'] -%}
{% set bearing = directions[ ((states("sensor.gw2000a_wind_direction") | int(0) / 22.5) | round(0) | int) ] %}
{{ bearing }}

You can try it inside the template editor in the DevTools.