Live weather conditions in my backyard.
(Updates automatically — no need to refresh)
How It Works
I have my own local Weather station in my yard because the microclimate here differs significantly from nearby official stations. A 10-degree mismatch can make the difference between wearing shorts and a t-shirt or jeans and a hoodie. The panel above updates every minute with live data from my backyard in east San Diego County. The server fetches the latest readings, processes them, and sends an updated display to your browser, giving you a real-time snapshot of the conditions here.
Weather Station Hardware
Ecowitt WS3900B
The Ecowitt WS3900B supplants my 8-year-old Ambient Weather station which stopped reporting wind data as its parts wore out. With no moving parts, the Ecowitt avoids mechanical failures. It has a piezoelectric rain gauge instead of a physical “funnel with tip bucket” that needed yearly cleaning to keep it recording properly. It also uses haptic/sonic wind detection technology instead of traditional moving cups or vanes.
Abstracting the Sensor Layer
This Home Assistant template provides weather station values via an abstracted sensor object. Using this in automations avoids discrete hardware references should I change equipment, which has happened before. As long as I can integrate a new station with this template, then all my previous automations continue to work.
{# WS3900B Forecast Approximation Template - Comprehensive #}
{# Uses current WS3900B sensors to approximate home_forecast #}
{% set solar = states('sensor.ws3900b_solar_radiation') | float(0) %}
{% set uv = states('sensor.ws3900b_uv_index') | float(0) %}
{% set rain_rate = states('sensor.ws3900b_rain_rate_piezo') | float(0) %}
{% set wind_gust = states('sensor.ws3900b_wind_gust') | float(0) %}
{% set wind_speed = states('sensor.ws3900b_wind_speed') | float(0) %}
{% set baro_now = states('sensor.ws3900b_relative_pressure') | float(0) %}
{% set baro_prev = states('sensor.ws3900b_pressure_3h_ago') | float(baro_now) %}
{% set baro_trend = baro_now - baro_prev %}
{% set humidity = states('sensor.ws3900b_humidity') | float(0) %}
{% set temp = states('sensor.ws3900b_outdoor_temperature') | float(50) %}
{% set dewpoint = states('sensor.ws3900b_dewpoint') | float(temp) %}
{% set temp_dewpoint_diff = temp - dewpoint %}
{% set recent_rain = states('sensor.ws3900b_hourly_rain_piezo') | float(0) %}
{% set daily_rain = states('sensor.ws3900b_daily_rain_piezo') | float(0) %}
{% set hour = now().hour %}
{# 1. Fog: temp near dewpoint, very high humidity, light/no wind, no gusts, no recent rain #}
{% if humidity > 95 and temp_dewpoint_diff < 3 and wind_speed < 3 and wind_gust < 5 and recent_rain == 0 %}
fog
{# 2. Snowy: freezing temp with precipitation #}
{% elif temp <= 32 and rain_rate > 0.02 %}
snowy
{# 3. Snowy-rainy: near-freezing with precipitation (mixed) #}
{% elif temp > 32 and temp <= 35 and rain_rate > 0.02 %}
snowy-rainy
{# 4. Pouring: heavy rain #}
{% elif rain_rate > 0.5 %}
pouring
{# 5. Lightning-rainy: rapid pressure drop with heavy rain (storm cell) #}
{% elif rain_rate > 0.2 and baro_trend < -0.3 and wind_gust > 15 %}
lightning-rainy
{# 6. Lightning: rapid pressure drop with high winds, no rain yet (approaching storm) #}
{% elif baro_trend < -0.3 and wind_gust > 20 and rain_rate == 0 %}
lightning
{# 7. Rainy: active rain OR recent rain OR significant daily rain with high humidity #}
{% elif rain_rate > 0.02 or recent_rain > 0 or (daily_rain > 0.1 and humidity > 90) %}
rainy
{# 8. Exceptional: extreme wind or catastrophic pressure drop #}
{% elif wind_gust > 50 or baro_trend < -0.5 %}
exceptional
{# 9. Windy-variant: strong sustained winds #}
{% elif wind_speed > 15 and wind_gust > 25 %}
windy-variant
{# 10. Windy: gusty conditions without rain #}
{% elif wind_gust > 20 and rain_rate == 0 %}
windy
{# 11. Night: low solar or before 6AM / after 8PM, if not fog/precip/wind #}
{% elif solar < 1 or hour < 6 or hour > 20 %}
clear-night
{# 12. Sunny: strong sunlight, UV, and steady/rising pressure #}
{% elif solar > 700 and uv > 3 and baro_trend >= -0.05 %}
sunny
{# 13. Partly cloudy: moderate sunlight #}
{% elif solar > 200 %}
partlycloudy
{# 14. Cloudy: fallback #}
{% else %}
cloudy
{% endif %}
Synthesized Conditions
This also attempts to synthesize the current weather conditions to imitate the string (sunny, cloudy, foggy, etc.) that MetNo uses. By using my hyperlocal sensor readings, it remains pretty accurate for my location. It likely needs more tuning.
Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.