XPLMWeather

To use:

import xp

This API provides access to the X-Plane enhanced weather system and requires at least X-Plane 12.04. More detailed weather, and the ability to set weather is available with 12.3.0.

All of these functions are relatively expensive, and should not be used per-frame.

Weather can perhaps best be characterized as a three-dimensional mesh, where each node in the mesh is connected to nearby nodes. Getting weather for a particular location retrieves an interpolated point within the mesh. Setting weather pushes or pulls a node, but the resulting value is tempered by the neighboring values: You can’t simply set a node’s temperature to 100°C with the surrounding nodes at 15°C and expect that value to hold.

See More about Weather for additional examples, cautions and explanations.

Theory of Operation

  • Get Weather

    • getMETARForAirport(): retrieve most recent METAR for given airport. Not necessarily an accurate representation of the current simulated weather. To get current weather at airport use getWeatherAtLocation() with the proper latitude, longitude.

    • getWeatherAtLocation(): retrieve weather details at particular latitude, longitude, and altitude. This returns the current simulated weather. The returned data structure depends on which version of X-Plane you are running, where version 12.3.0 adds more data elements. You can query xp.XPLMWeatherInfo_t to get a full description.

  • Set Weather

    Setting weather will not change the UI “Weather Settings”: however, weather set via plugin “adds” to the set of information used to calculate simulated weather.

    • setWeatherAtLocation(): sets (or perhaps “injects” is better…) weather at a particular latitude, longitude. This data is further combined with otherwise existing data to result in new weather. Your weather update merely influences the current weather simulation: the more data you inject (say over a particular region) the greater the effect. You’ll provide an altitude with this function call. Think of this altitude as the location of a weather-reporting station e.g., “ground level”.

    • setWeatherAtAirport(): sets (“injects”…) weather at a particular airport. This can be interpreted as replacing a previously downloaded METAR. This data is further combined with otherwise existing data to result in new weather. Your weather update merely influences the current weather simulation.

    • eraseWeatherAtLocation(): removes all weather effects your plugin has injected for the given location. If other plugins have changed the weather, those plugin effects are still valid. Weather specified using setWeatherAtAirport() is not effected by this function even when the latitude & longitude are the same.

    • eraseWeatherAtAirport(): removes all weather effects your plugin has injected for the given airport, similar to eraseWeatherAtLocation().

    • beginWeatherUpdate(), endWeatherUpdate(): To facilitate making multiple changes to the weather, you should bracket your changes between “begin” and “end”. This function pair also allows you to indicate your changes are incremental, and if your changes should take effect “immediately” (as might be useful on startup) or transitioned over the next few minutes. For programming convenience, we’ve included a context manager weatherUpdateContext() to avoid mishandling an “end”.

And, because someone asked: Yes, you can set weather even when using “Real-world weather”. Your report will age and eventually be replaced by newer “real-weather”.

Get Weather

getMETARForAirport(airport_id)
Parameters

airport_id (str) – ICAO code

Returns

Last known METAR for airport (str)

Get the last known METAR report for an airport by ICAO code. Note that the actual weather at that airport may have evolved significantly since the last downloaded METAR. This call is not intended to be used per-frame.:

>>> xp.getMETARForAirport('KJFK')
'KJFK 111451Z 01012KT 7SM -RA OVC011 03/02 A2974 RMK AO2 SNB1356E02 SLP070 P0005 60015 T00280017 51024'
>>> xp.getMETARForAirport('JFK')
''
>>> xp.getMETARForAirport('KNYC')
''

Note that valid METAR codes which are not airports such as Central Park NYC (KNYC) do not return values.

Note also that “Download Real Weather” must be enabled in order for X-Plane to have downloaded any METARs. If real weather was not enabled, the query will return an empty string with no indication that real weather is disabled.:

>>> xp.getMETARForAirport('KJFK')
''

Official SDK XPLMGetMETARForAirport

getWeatherAtLocation(latitude, longitude, altitude_m)
Parameters
  • latitude (float) –

  • longitude (float) – A “nearby” location

  • altitude_m (float) – Altitude (MSL) in meters

Returns

XPLMWeatherInfo_t or None on error.

Get the current weather conditions at a given location. Note that this is not effective outside the surrounding region.

This call is not intended to be used per-frame (use datarefs if at all possible instead).

Returns None on error.

  • This function will appear to execute world-wide, with latitudes +/- 90 degrees and longitudes +/- 180 degrees. However, weather outside the current region will be less accurate, due to math errors and METAR information. (There is no way of knowing the extent of the current region, so the understanding should be “nearby weather is more accurate that far-away weather”. Generally, within 50nm of current location has good accuracy.) Using values with illegal latitude/longitude range will result in a None return value.

  • The XPLMWeatherInfo_t.detail_found attribute, on a successful return, is the actual return value from X-Plane’s XPLMGetWeatherAtLocation() call. This, I’m told, indicates “if detail weather is found”, where detail weather refers to the existence of a METAR within about 50 miles of the queried location. It is not a success/failure return value of the actual XPLMWeatherInfo_t object. (Nor is it an indication of “weather in region” vs. “weather out of region”.)

    What to do with this detail_found value? Beats me. It won’t tell you which METAR is nearby, or which of multiple nearby METARs are used perhaps to alter the world-wide GRIB weather data. Bug Report has been filed requesting clarification.

    Because detail_found does not indicate success or failure, XPPython3 uses a flag to attempt to detect if data is valid. (We set an internal data structure temperature to a bogus number and if post-query it is still bad, we assume data was not successfully obtained, and return None.)

On success, getWeatherAtLocation() returns a XPLMWeatherInfo_t object. See below for details or interactively using help(xp.XPLMWeatherInfo_t). The WeatherInfo object includes a list of wind layers XPLMWeatherInfoWinds_t, a list of cloud layers XPLMWeatherInfoClouds_t, and a list of floats for temperature and dewpoint layers.

For example:

>>> info = xp.getWeatherAtLocation(34, -117, 2000)
>>> print(info)
<XPLMWeatherInfo_ object> 7.9/-10.1 252@3 QNH1009
>>> info.temperature_alt
7.93484
>>> info.dewpoint_alt
-10.11784
>>> info.wind_dir_alt
252.4056
>>> info.wind_speed_alt
1.4252
>>> len(info.wind_layers)
13
>>> [x.alt_msl for x in info.wind_layers]
[0.0, 540.1, 988.5, 1948.3, 3010.8, 4206.5, 5572.0, 7182.3, 9160.1,
 10362.9, 11887.2, 13594.1, 16179.4]
>>> print(info.wind_layers[0])
<XPLMWeatherInfoWinds_t object> 175@9 at 0.0m MSL
>>> print(info.wind_layers[1])
<XPLMWeatherInfoWinds_t object> 176@10 at 540.1m MSL
>>> print(info.cloud_layers[1])
<XPLMWeatherInfoClouds_t object> 2.0 (50%) from 4442.0m to 5759.5m

If coverage is zero, there are no clouds at that layer regardless of the other parameters. Just skip that layer and look at the next.

Though not documented, I assume “cloud type” enumeration is the same as the sim/weather/aircraft/cloud_type and sim/weather/region/cloud_type datarefs:

0 = Cirrus
1 = Stratus
2 = Cumulus
3 = Cumulonimbus

Official SDK XPLMGetWeatherAtLocation

Set Weather

Warning

“Setting Weather” is available only with X-Plane 12.3.0 and above, which is currently in beta. There remain some bugs in the X-Plane implementation, so the following API and/or explanations may change.

The following functions are only available with X-Plane 12.3.0+. Calling them on earlier versions of X-Plane will log an error.

You must batch weather updates, surrounding them within the same callback with a begin/end or an update context. Never simply call setWeatherAt*().

The weather updates you provide, be they new observation using setWeatherAt*() or removing previous observations using eraseWeatherAt*(), are normally transitioned over the next few minutes, unless they are surrounded with an “updateImmediately” begin/end context. Additionally, each setWeatherAt*() call results in incremental updates to plugin weather data already provided (i.e., “isIncremental”) for all locations from any python plugin. If you want to reset weather (“now dammit!”) use a non-incremental weather context and don’t provide any weather setting:

>>> with xp.weatherUpdateContext(isIncremental=0, updateImmediately=1):
...     pass

Note that isIncremental=0 removes all previously set weather, at the same and other locations. Additionally, because all XPPython3 plugins are considered a single plugin by X-Plane, your incremental will apply to all other python plugins as well. (You cannot erase or clear weather created by other non-python plugins: you can add your observations at the same location which will cause the Laminar weather engine to alter its view of the current weather.)

If you only want to remove selected updates, use isIncremental=1 and eraseWeatherAt*(), matching locations or airports for which you’ve previously provided weather.

Important

Three attributes are critical to setting weather as otherwise you will waste your time debugging (ask me how I know).

  • age: How recent is this report? Set to 0 to have full impact.

  • radius_nm: Horizontally, what is the effective radius of this report? Default is 30nm. If it’s zero, you’ll set weather only at a point in space, not very useful.

  • max_altitude_msl_ft: Vertically, limit the effect of this report to be no higher than this value. Default is 10000 feet MSL. You can’t set the height of the troposphere (~36000’) if you’re limiting the effect to 10000’. Similarly, setting values for temperature or wind layers above 10000’ would not take effect.

One caution here is, if you start with a WeatherInfo_t value obtained from getWeatherAtLocation(), you must set radius_nm and max_altitude_msl_ft as they will both be zero on return from xp.getWeatherAt* calls.

setWeatherAtLocation(latitude, longitude, altitude_m, info)
Parameters
  • latitude (float) –

  • longitude (float) – floating point latitude and longitude

  • ground_altitude_msl (float) – pseudo-altitude of reporting station to calibrate QNH in feet

  • info (XPLMWeatherInfo_t) – XPLMWeatherInfo_t data structure containing requested change. Note not all element members are applicable for “set”.

Set the current weather conditions at a given location, as if the reporting station were at ground_altitude_msl. Weather effected is from 0 MSL up to the value of max_altitude_msl_ft, with a horizontal radius of radius_nm in the passed XPLMWeatherInfo_t data structure.

Official SDK XPLMSetWeatherAtLocation

setWeatherAtAirport(airport_id, info)
Parameters
  • airport_id (str) – airport ID

  • info (XPLMWeatherInfo_t) – XPLMWeatherInfo_t data structure containing requested change. Note not all element members are applicable for “set”.

See setWeatherAtLocation(). This function is nearly identical to setWeatherAtLocation(), where the latitude, longitude, and altitude are derived from the airport ID. You still need to set radius_nm and max_altitude_msl_ft.

Official SDK XPLMSetWeatherAtAirport

eraseWeatherAtLocation(latitude, longitude)
Parameters
  • latitude (float) –

  • longitude (float) – floating point latitude and longitude

Erase all weather information provided by this plugin at the given latitude, longitude. Note if other plugins have also provide weather at this location, those changes will still be valid. It is not harmful to call eraseWeatherAtLocation() where you have not yet provided weather.

Official SDK XPLMEraseWeatherAtLocation

eraseWeatherAtAirport(airport_id)
Parameters

airport_id (str) – airport ID

Erase all weather information provided by this plugin at the given airport. Note if other plugins have also provide weather at this airport, those changes will still be valid. It is not harmful to call eraseWeatherAtAirport() where you have not yet provided weather.

Official SDK XPLMEraseWeatherAtAirport

Update Context

You must surround your weather updates (set and erase) with a begin/end context, or use the python weatherUpdateContext() context. Additionally, a set of updates must occur within a single callback thread: You can have different updates in different threads, but each set must include begin/end context.

beginWeatherUpdate()

Inform the simulator that you are starting a batch update of weather information. You must call endWeatherUpdate() prior to exiting your callback. Failure to do so will result in error and performance issues. For this reason, we suggest you use weatherUpdateContext() instead.

Because this function must be used at the same time as endWeatherUpdate(), you cannot type this function directly into the python debugger (though you can, if you place it within a function definition.) Use weatherUpdateContext() if you want to experiment within the debugger.

This call is not intended to be used per-frame.

>>> def changeWeather():
...    xp.beginWeatherUpdate()
...    info = xp.getWeatherAtLocation(35, -172, 100)
...    info.thermal_climb += .5
...    xp.setWeatherAtLocation(35, -172, 100, info)
...    xp.endWeatherUpdate()
...
>>> changeWeather()

or, using the context manager:

>>> with xp.weatherUpdateContext():
...   info = xp.getWeatherAtLocation(35, -172, 100)
...   info.thermal_climb += .5
...   xp.setWeatherAtLocation(35, -172, 100, info)
...

Official SDK XPLMBeginWeatherUpdate

endWeatherUpdate(isIncremental=1, updateImmediately=0)
Parameters
  • isIncremental (int) – Make incremental update or over-write plugin weather

  • updateImmediately (int) – Make changes immediately, or transition to the requested change over the next few minutes.

Inform the simulator that you are ending a batch update of weather information. Incremental updates add to any previous weather update you’ve provided. Otherwise, you will replace all of your plugin weather associated with this location. This makes is possible to only update a fraction of your weather data at any one time.

The normal mode of operation is that you are setting the weather “in the near future”. Currently this is somewhere between one and two minutes (though this may change). Setting future weather ensures that there is no sudden jump in weather conditions. In some situations, notably for an initial setup, you may want to ensure that the weather is changed instantly. To do this, set updateImmediately to one.

This call is not intended to be used per-frame.

Official SDK XPLMEndWeatherUpdate

weatherUpdateContext(isIncremental=1, updateImmediately=0)
Parameters
  • isIncremental (int) – Make incremental update or over-write plugin weather

  • updateImmediately (int) – Make changes immediately, or transition to the requested change over the next few minutes.

This is a context manager which can be used to enforce calling beginWeatherUpdate() and endWeatherUpdate(). Additionally, if your code has a bug in it, we’ll catch it and call endWeatherUpdate() to avoid catastrophe. It is the preferred way of specifying context rather than using the two functions to begin and end the update:

>>> with xp.weatherUpdateContext(updateImmediately=1):
...     xp.eraseWeatherAtLocation(35, -177)
...     xp.setWeatherAtLocation(35, -177, 100, info)
...     xp.setWeatherAtLocation(35, -177.5, 100, info)
...     xp.setWeatherAtLocation(35, -178.0, 100, info)
...
>>>

Types

Weather data is stored within an instance of

Each of these types are described below.

XPLMWeatherInfo_t

Weather information is stored in the XPLMWeatherInfo_t type. It is represented in XPPython3 as a class. As with most python, you can get more information about it using help(xp.XPLMWeatherInfo_t).

This type was introduced in X-Plane 12.0, and then expanded with more fields in X-Plane 12.3.0. You can use this class with any X-Plane 12.0+, though some of the fields will not have meaning unless used with 12.3.0+

Various fields within this class interact with each other.

You can create a “blank” instance of this class, including associated lists by normal python means.:

>>> info = xp.XPLMWeatherInfo_t()

The instance will be initialized to useful defaults including:

.age = 0
.detail_found = -1
.radius_nm = DefaultWxrRadiusNm
.max_altitude_msl_ft = DefaultWxrLimitMslFt
.temp_layers = [None, None, …, None]
.dewp_layers = [None, None, …, None]
.cloud_layers = [xp.XPLMWeatherInfoClouds_t(0, 0, 0, 0), … ]
.wind_layers = [xp.XPLMWeatherInfoWinds_t(0, -1, 0, 0, 0, 0), … ]

Field

Type

Description

Get/Set

X_Plane_Version

detail_found

int

Return value from xp.getWeatherAtLocation(). 1=’detailed weather found’. Not meaningful otherwise.

Get

12.0-Read

temperature_alt

float

Temperature at altitude (Celsius).

To set temperature, use this parameter to set the ground-level temperature, and temperatures above ground level will be calculated using standard lapse rate. Set this to None (or -274) to ignore setting.

You can also use ‘temp_layers’ which explicitly set temperatures at one or more altitude layers. Or, set this to None (or -274) and only use ‘temp_layers’.

The calculated temperatures during a read are also affected by the troposphere altitude and temperature, and the vertical limit of the effect. Do not expect to get the exact values you set.

Get/Set

12.0-Read
12.3-R/W

dewpoint_alt

float

Dewpoint at altitude (Celsius).

Similar to temperature_alt (and temp_layers)

Get/Set

12.0-Read
12.3-R/W

pressure_alt

float

Pressure at altitude (Pascals).

On set, should be QNH as reported by station at the named station or provided ground_altitude_msl, or set this to 0 and set sealevel pressure in ‘pressure_sl’ instead.

Get/Set

12.0-Read
12.3-R/W

precip_rate_alt

float

Precipitation rate at altitude (0.0 - 1.0)

Ignored on set.

Get

12.0-Read

wind_dir_alt

float

Wind direction at altitude. (0.0 - 360.0)

Ignored on set. (Use wind_layers.)

Get

12.0-Read

wind_spd_alt

float

Wind speed at altitude (meters/second).

Ignored on set. (Use wind_layers.)

Get

12.0-Read

turbulence_alt

float

Clear-air turbulence ratio at altitude. (Values to be determined)

Ignored on set. (Use wind_layers)

Get

12.0-Read

wave_height

float

Wave height (meters)

Get/Set

12.0-Read
12.3-R/W

wave_length

float

Wave length (meters).

Ignored on set. (Derived from other data)

Get

12.0-Read

wave_dir

int

Wave direction (waves coming from…) degrees.

Get/Set

12.0-Read
12.3-R/W

wave_speed

float

Wave speed (meters/second).

Ignored on set. (Derived from other data.)

Get

12.0-Read
12.3-R/W

visibility

float

Base visibility at 0 altitude (distance in meters)

Get/Set

12.0-Read
12.3-R/W

precip_rate

float

Base precipitation ratio at 0 altitude. (0.0 - 1.0)

Get/Set

12.0-Read
12.3-R/W

thermal_climb

float

Climb rate due to thermals (meters/second)

Get/Set

12.0-Read
12.3-R/W

pressure_sl

float

Pressure at sealevel (Pascals).

On set, this is ignored if ‘pressure_alt’ is non-zero.

Get/Set

12.0-Read
12.3-R/W

wind_layers

list

List of up to NumWindLayers XPLMWeatherInfoWinds_t objects.

Not all wind layers are always defined.

Get/Set

12.0-Read
12.3-R/W

cloud_layers

list

List of up to NumCloudLayers XPLMWeatherInfoClouds_t objects.

Not all cloud layers are always defined.

Get/Set

12.0-Read
12.3-R/W

temp_layers

list

List of floats for temperature in Celsius at predefined atmosphere levels.

For layer altitudes, see dataref ‘sim/weather/region/atmosphere_alt_levels_m’.

On set, if temp_layers[x] is None (or <= -274.), ‘temperature_alt’ or other existing data is used and lapse rate is applied.

Get/Set

12.3

dewp_layers

list

List of floats for dewpoints in Celsius at predefined atmosphere levels.

For layer altitudes, see dataref ‘sim/weather/region/atmosphere_alt_levels_m’.

On set, if dewp_layers[x] is None (or <= -274.), ‘dewpoint_alt’ or other existing data is used and lapse rate is applied.

Get/Set

12.3

troposphere_alt

float

Altitude of troposphere in meters.

On set, if this is 0 or lower, ‘troposphere_alt’ and ‘troposphere_temp’ will be derived from existing data.

Altitude and temperature may be clamped to internally-defined ranges.

Get/Set

12.3

troposphere_temp

float

Temperature in Celsius of troposphere.

On set this is ignored when troposphere_alt is 0 or less.

Get/Set

12.3

age

float

Age in seconds of this weather report. Age affects how strongly the report affects the weather. Commonly, you will set this to zero so you change will be effective.

This is meaningless on read and should be zero.

Set

12.3

radius_nm

float

Horizontal radius of effect of this weather report, nautical miles. You need to set this to something.

This is meaningless on read.

Set

12.3

max_altitude_msl_ft

float

Vertical limit of effect of this weather report, feet MSL. You need to set this to something.

This is meaningless on read.

Set

12.3

When setting both temperature and dewpoint from a single value (temperature_alt / dewpoint_alt), the rest of the atmosphere will be graded to fit between the given values and the troposphere values.

XPLMWeatherInfoClouds_t

Field

Type

Description

Get/Set

X_Plane_Version

cloud_type

float

Cloud Type, effectively an enumeration:

0 = Cirrus
1 = Stratus
2 = Cumulus
3 = Cumulo-nimbus

Get/Set

12.0-Read
12.3-R/W

coverage

float

Coverage radio (0.0 - 1.0)

Get/Set

12.0-Read
12.3-R/W

alt_top

float

Altitude of cloud top. (MSL in meters)

When alt_top == alt_base, the cloud layer is undefined.

Get/Set

12.0-Read
12.3-R/W

alt_base

float

Altitude of cloud base. (MSL in meters)

Get/Set

12.0-Read
12.3 R/W
XPLMWeatherInfoWinds_t

Field

Type

Description

Get/Set

X_Plane_Version

alt_msl

float

Altitude of wind layer. (MSL in meters)

(Depth of wind layer is not specified.)

Get/Set

12.0-Read
12.3-R/W

speed

float

Wind speed (meters/second)

On set if this is WindUndefinedLayer (-1), this layer is undefined and (effectively) skipped.

You can have defined layers above undefined layers.

Get/Set

12.0-Read
12.3-R/W

direction

float

Wind direction (degrees True) (0.0-360.0)

Get/Set

12.0-Read
12.3-R/W

gust_speed

float

Gust speed, (meters/second). This is the total speed, not the amount of increase over the wind speed.

Get/Set

12.0-Read
12.3-R/W

shear

float

Shear arc, degrees. The wind will shear 50% of this arc in either direction from base direction.

Get/Set

12.0-Read
12.3-R/W

turbulence

float

Clear Air Turbulence ratio

Get/Set

12.0-Read
12.3-R/W

Constants

NumWindLayers = 13

Length of the list of .wind_layers in XPLMWeatherInfo_t.

Official SDK XPLM_NUM_WIND_LAYERS

NumCloudLayers = 3

Length of the list of .cloud_layers in XPLMWeatherInfo_t.

Official SDK XPLM_NUM_CLOUD_LAYERS

NumTemperatureLayers = 13

Length of the list of .temp_layers and .dewp_layers in XPLMWeatherInfo_t.

Official SDK XPLM_NUM_TEMPERATURE_LAYERS

WindUndefinedLayer = -1

Value to use as the wind speed in .wind_layer item to cause this layer to be ignored (i.e., “no data” vs. “zero wind”).

Official SDK XPLM_NUM_UNDEFINED_LAYER

DefaultWxrRadiusNm = 30

Default horizontal radius of weather data points set using XPLMSetWeatherAtLocation and XPLMSetWeatherAtAirport. Note you still need to specify this (or another) value on set.

Official SDK XPLM_DEFAULT_WXR_RADIUS_NM

DefaultWxrLimitMslFt = 10000

Default vertical limit of weather data points set using XPLMSetWeatherAtLocation and XPLMSetWeatherAtAirport. Note you still need to specify this (or another) value on set.

Official SDK XPLM_DEFAULT_WXR_LIMIT_MSL_FT