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 usegetWeatherAtLocation()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 queryxp.XPLMWeatherInfo_tto 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 usingsetWeatherAtAirport()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 toeraseWeatherAtLocation().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 managerweatherUpdateContext()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_tor 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
Noneon 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
Nonereturn value.The
XPLMWeatherInfo_t.detail_foundattribute, 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_foundvalue? 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_founddoes 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 returnNone.)
On success,
getWeatherAtLocation()returns aXPLMWeatherInfo_tobject. See below for details or interactively usinghelp(xp.XPLMWeatherInfo_t). The WeatherInfo object includes a list of wind layersXPLMWeatherInfoWinds_t, a list of cloud layersXPLMWeatherInfoClouds_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
coverageis 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_typeandsim/weather/region/cloud_typedatarefs:0 = Cirrus1 = Stratus2 = Cumulus3 = CumulonimbusOfficial 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_tdata 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 ofmax_altitude_msl_ft, with a horizontal radius ofradius_nmin the passedXPLMWeatherInfo_tdata structure.Official SDK XPLMSetWeatherAtLocation
- setWeatherAtAirport(airport_id, info)¶
- Parameters
airport_id (str) – airport ID
info (XPLMWeatherInfo_t) –
XPLMWeatherInfo_tdata 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 setradius_nmandmax_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 useweatherUpdateContext()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.) UseweatherUpdateContext()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
updateImmediatelyto 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()andendWeatherUpdate(). Additionally, if your code has a bug in it, we’ll catch it and callendWeatherUpdate()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
XPLMWeatherInfo_t, which includes lists 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 |
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 Not all wind layers are always defined. |
Get/Set |
12.0-Read
12.3-R/W
|
cloud_layers |
list |
List of up to 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
|
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:
|
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
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_layersinXPLMWeatherInfo_t.Official SDK XPLM_NUM_WIND_LAYERS
- NumCloudLayers = 3¶
Length of the list of
.cloud_layersinXPLMWeatherInfo_t.Official SDK XPLM_NUM_CLOUD_LAYERS
- NumTemperatureLayers = 13¶
Length of the list of
.temp_layersand.dewp_layersinXPLMWeatherInfo_t.Official SDK XPLM_NUM_TEMPERATURE_LAYERS
- WindUndefinedLayer = -1¶
Value to use as the wind speed in
.wind_layeritem 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
