Local/offline/self-hosted weather forecast?

I have been testing this for a bit and I like the results.
When I have 27% chance of Fog, there is not fog directly at my house but fog has been present about 3 miles from my house. This has been verified on multiple days.

FYI: Zambretti is now in WeatherFlow2MQTT (not just Dev build now).
When do you expect to get your Tempest?

A few weeks ago :wink:

Oh fantastic - I’ve been keeping an eye on it in my RSS reader but I’m a few thousand articles behind up-to-date so I haven’t seen anything about it yet. I’ll do an update on my LXC container later tonight :grinning:

Hi,
random lurker here (actually one who was professionally taught the pilot version of the snow line formula, but relies on the forecasters these days :snowman:).

Very interesting topic!

It seems your absolute humidity is very high, like a factor 10?

There is a few breaking changes.
Please verify for yourself, but I think these are the only environmental variables that are all new since the last stable release:

-e LATITUDE=0 \
-e LONGITUDE=0 \
-e ZAMBRETTI_MIN_PRESSURE=960
-e ZAMBRETTI_MAX_PRESSURE=1060

I run the Dev build, so the Lat and Long may have been in the last stable release but I think they are all new for this stable release. The Docker Hub ‘overview’ page is not up-to-date (will be soon-ish), so use the GitHub ReadMe https://github.com/briis/hass-weatherflow2mqtt.

I have my Solar Insolation in here which is the estimate of Solar Radiation without clouds. I would appreciate any feedback for other latitudes. For me, it tracks fairly well. I use this for the local ‘current conditions’ which will be in the dev build soon and then hopefully not too long later in the stable build. I also plan on getting Fog and Snow probability in the next build.

@JeeCee You posted as I was writing this…what do you use for your absolute humidity calculation? I have an approximation but want to compare it to what others may be using.

From ESPHome code:

  const float mw_1 = 18.01534;    // molar mass of water g/mol
  const float r_1 = 8.31447215;   // Universal gas constant J/mol/K
  return (6.112 * powf(2.718281828, (17.67 * id(bme280_1_temperature).state) /
    (id(bme280_1_temperature).state + 243.5)) * id(bme280_1_humidity).state * mw_1) /
    ((273.15 + id(bme280_1_temperature).state) * r_1); // in grams/m^3

I’ve never had any use for absolute humidity, nor do I understand how to use it.
Where exactly is my absolute humidity really high? If you mean on the snow page on BordersWeather then that figure is coming from WeatherDisplay and it may be that either the version of Weather Display that I run had an error that was subsequently fixed in one of the many many many versions that were released after my installed version, or it may have never been fixed - I don’t know, it’s never bothered me, because like I said - I have no real use for it.

Quick question Glenn, I have the new version up and running, and I note that the Zambretti forecast changes several times an hour. I assume this is calculated frequently rather than just at 9am? How do you personally deal with this? create a helper with an automation that captures the value at 9am and stores it - or do you just let it change about as it does?

Mine is swapping between Fairly fine, showers likely and Showery, bright intervals

We had issues with the ‘Trend’ part of the Zambretti; Rising or Falling is any 1.6MB change in 3 hours and steady is if no rise or fall of 1.6 in the last 3 hours. This is still a work in progress, but it is usable until this is fixed.

It is calculated constantly and not just at 9am.

It is also important that your Pressure range is correct, the High and Low variables. If you have historical data that is the best way to go or there are some weather sites that have record highs and lows for the past year.

I do let it change for now, but I am currently graphing out the ‘Zambretti Number’ which can help in trend analysis. I intentionally put out a Number and not a Letter to enable graphing. Numbers 0-25 correspond to Zambretti Letters A-Z.

As far as I can tell the reason for the original 9am was that shortly after sunrise follows a lowering trend (gradual) in pressure on a standard day.

I saw it here:

I had mold in my basement so I wanted to track the water amount in the air and see if it reduced after
installing ventilation, the jury is still out.

Also, the way I understand it, water quantity does not change a lot locally, but since temperature does so does RH; so absolute humidity is a better indicator of how “wet” the air is (e.g. in the bathroom after a shower)

1 Like

I have used my historical data back to 2007 - which matches the high and low that Beteljuice was using anyway. I’m wondering though, since the forecast relies on wind direction being correct, if it is being affected by the issue that I have seen mentioned by other people - which is that when there is no wind being recorded at all, the WeatherFlow defaults to reporting North as the direction, instead of as it should be doing - simply maintaining the last wind direction that wind was reported as coming from.

Eg:

if current_wind_speed > 0 {
  last_good_bearing = current_wind_bearing
}
if current_wind_bearing == 0 and current_wind_speed == 0 {
  current_wind_bearing = last_good_bearing
}

I originally had air speed in but removed it for some reason I can’t remember at this time. I do know that I used the average wind direction to help negate some of the lack of wind.

I just looked through my history and the only time I have a North wind direction is during 10mph+ wind speed. I have 80 degree wind direction 99% of the time. The Beteljuice algorithm expects a nonsensical wind direction if there is no wind (<1mph), which is what I originally did but something wasn’t working so just always used average direction.

I fully expected to be making tweaks to it once others started using it. I only tested for my specific location and it seems to track for me, but I think we have only had maybe 10 days without rain this entire year so it is not hard to predict rain.

I did think about doing an array that stored 12 points for the Zambretti since it is an estimate for about 12 hours out and then displaying the zambretti that was predicted 12 or 11 hours ago. I was going to do an average of the last hour and store that. I did not go down this path but might revisit that idea later. I liked the graph so I just stuck with that, since the higher the number the more likely the chance of rain. I was looking around to see if anyone had tried to approximate the probability of rain based on the Zambretti but did not find anything useful; I am gathering my data to see if there is a useful approximation I can implement. It would be something similar to you Fog probability but probably based solely on the Zambretti output; I did think about just dividing 100/26 and and go up from there but that is a little too simplistic (still might do it thou).

Well it is a bit unsettled today, but we are about to get an extended period of hot and settled weather, possibly with some record breaking temperatures. So I will be a good a test bed for you.

This though - is how my graph currently looks:

Which is why I thought I should query whether it was better to take a snapshot at 9am (for me).

Tempest and WeatherFlow however use a 1 min average for the average direction, and since direction of the wind is pretty important to the calculations for Zambretti - it might be better to use a simple moving average time window of 10-15 minutes to get a more stable average direction.

Average Wind:

Note - that the Tempest is not in a final location yet, so I haven’t gone about contacting support for calibration until I know it is where it is going to stay permanently.

This is my much more stable WS2305 average direction sampled at 5 minutes from Weather Display.

That Tempest Wind Bearing is all over the place, you are correct that will defiantly effect your Zambretti output. The Zambretti uses the cardinal direction, so that does ‘average’ out some of the turbulance along with the actual ‘average’ wind direction.

Your Zambretti output does not actually look too bad up to 1030, after that it is a bit of a mess but not seemingly based on wind direction. I will post a picture of my Zambretti when I get back home.

For my testing I had graphs for Solar Elevation, Solar Radiation, Solar Insolation, Wind Direction, Wind Speed, Zambretti Number, and Sea Level Pressure. The first 3 don’t apply too much directly to Zambretti, but I would like others to compare these and give feedback. I still have everything other than wind listed, but I can add them back to see if there is anything that stands out every now and then. I did find that the Solar Elevation was useful in comparison to Sea Level Pressure. I also have/had a few other things displayed for testing but removed them as things went together.

1 Like

Untitled
Mine moves, but not as extreme as yours.

@mobile.andrew.jones

I’ve been working on some tweaks for snow probability:
I have this in python for the integration, if this works better, I’m still testing. I’m testing in Java-Script currently.

    def snow_probability(self, air_temperature, freezing_level, cloud_base, dew_point, wet_bulb, station_height, wind_speed, relative_humidity):
        """ Return probability of snow in percent (Max of 80% calculated probability).
        Input:
            Air Temperature (metric)
            Freezing Level (imperial or metric)
            Cloud Base (imperial or metric)
            Dew Point (metric)
            Wet Bulb (imperial or metric))
            Station Height (metric)
            Wind Speed (imperial or metric)
            Relative Humidity (percentage)
        Where:
            dptt is Dew Point plus Air Temperature
            snow_prob is the probability of snow
            snow_probability is the returned percentage of the probability of snow rounded (Max of 80%)
        """

        if (
            air_temperature is None
            or freezing_level is None
            or cloud_base is None
            or dew_point is None
            or wet_bulb is None
            or wind_speed is None
            or relative_humidity is None
        ):
            return None

        is_metric = False if self.unit_system != UNITS_IMPERIAL else True

        if not is_metric:
            air_temperature = air_temperature
            freezing_level = freezing_level / 3.28
            cloud_base = cloud_base / 3.28
            dew_point = dew_point
            wet_bulb = (wet_bulb - 32) / 1.8
            station_height = station_height
            wind_speed = wind_speed
            
        snow_line = freezing_level - 228.6 # 750 ft / 228.6 m, snow line can vary in distance from freezing line
        dptt = dew_point + air_temperature

        if (
            (air_temperature <= 2.1) and 
            (snow_line <= station_height) and 
            (dew_point <= 1) and 
            (wet_bulb <= 2.1) and 
            (freezing_level <= cloud_base) and 
            (air_temperature >= -40) and
            (wind_speed <= 10) and
            (relative_humidity <= 70)
        ):
            snow_prob = 80 - 10 * dptt
        else:
            snow_prob = 0

        snow_probability = round(snow_prob) if snow_prob <= 100 else 99
        return snow_probability

Mostly looking good to me, just a few questions though…

(and apologies if I am being a bit slow here, it’s almost 5am and I am just heading to sleep)

I am confused by this point, surely if self.unit_system is NOT equal to UNITS_IMPERAL then it must be metric? So I don’t understand this line, which would appear to set is_metric to True when the units are imperial, and False when the units are metric?

Additionally:

Shouldn’t the wind speed be converted to a standard unit like you have done with temperature etc, in order to make use of it later in your probability generation code - which currently only cares if the Wind Speed is less than or equal to 10, irrespective of what unit the wind speed is measured in.

Additionally - could you give a bit of insight behind the wind speed needing to be low? When blizzards occur, the wind speed is not <= 10

Andy

Somehow I did not copy the latest code.
I converted wind speed and dew point also and I also added relative humidity…
Here is what I have, still testing, and I will look at the imperial/metric check; it looks like you are right, but I’m in the same condition you are in about to go to bed and I just had a free min that turned into a few hours bashing this out.
Ah, I remember, I made changes to they Java Script after making the python version.

Here is the java-script:

// Probability of Snow

var air_temperature = msg.temperature;
var freezing_level = msg.freezing_level;
var cloud_base = msg.cloud_base;
var dew_point = msg.dew_point;
var wet_bulb = msg.wet_bulb;
var station_height = msg.station_height;
var wind_speed = msg.wind_speed;
var relative_humidity = msg.relative_humidity;

var snow_prob = 0;

// convert inputs to metric as required
air_temperature = (air_temperature - 32) * 5/9;
freezing_level = freezing_level / 3.28;
cloud_base = cloud_base / 3.28;
dew_point = (dew_point - 32) * 5/9;
wet_bulb = (wet_bulb - 32) * 5/9;
station_height = station_height;
wind_speed = wind_speed * 0.44704;
relative_humidity = relative_humidity;

var snow_line = freezing_level - 228.6; // 750 ft / 228.6 m, snow line can vary in distance from freezing line
var dptt = dew_point + air_temperature;

if (
    (air_temperature <= 2.1) && 
    (snow_line <= station_height) && 
    (dew_point <= 1) && 
    (wet_bulb <= 2.1) && 
    (freezing_level <= cloud_base) && 
    (air_temperature >= -40) &&
    (wind_speed <= 4.472) &&
    (relative_humidity <= 70)
) {
    snow_prob = 80 - (10 * dptt);
} else {
    snow_prob = 0;
}

var snow_probability = Math.round(snow_prob);

if (snow_prob > 100) {
    snow_probability = 100;
}

msg.snow_prob = snow_probability;
return msg;

I was researching conditions that have effect on snow and thought I could improve this. I am limiting my conditions to what we can get from the Tempest.

I see some more corrections, or simplification, not sure why I declared the varaiables then converted them later, I thought I did that on the same line…BED TIME

1 Like

Hey Glenn,
That looks better.

I would just like to request that to reduce the chances of missing out on probabilities that should generate a high number, but don’t with this code, wind speed should be increased from it’s current Beaufort level of 3 (Gentle Breeze, <=5.4 m/s), to either 4 (Moderate Breeze, <= 7.9 m/s) or 5 (Fresh Breeze, <= 10.7 m/s).

Additionally, perhaps the option to use wind speed in the probability calculation could be an optional environment variable (simply set the wind speed to 0, after the conversions etc, if they choose not to involve the wind speed)

Andy

after more research, it does look like in colder temperature snow can still form in high wind speeds; so I will remove it for now. I will see if I can correlate wind speed and temperature and see if I can do anything with that.

1 Like

It might be better to focus on the relative humidity instead.
If the temperature is well below freezing, humidity doesn’t play as big a factor in determining whether snow will fall, eg according to the UK Met Office 100% humidity at -6.7C is fine for snow. But the closer you get to 0C the lower the humidity needs to be, The UK Met Office suggests lower than 40% at around -1C

You may be able to work with that, instead of your existing <= 70 to be able to more accurately calculate whether it will be snow or rain.

EDIT:
Looks like we will both be giving this a read: Spatial variation of the rain–snow temperature threshold across the Northern Hemisphere | Nature Communications
:joy:

I like it, that is EXACTLY the kind of info I needed:

Each 10% increase in RH is associated with a 0.8 °C decrease in the 50% rain–snow T s threshold

I think I will spend some time review that article and completely revamp the snow probability. I’ll post what I come up with, but if you beat me too it…you won’t hurt my feelings.

Edit: I should have kept looking down, they have their own probability formula. I don’t readily see their model constants though; that is the values of those constants.

1 Like