Ветер на высотах
Прогнозы ветра на высотах описывают ожидаемое направление и скорость ветра и температуру на стандартных высотах для планирования полётов в США. FB Winds (Winds and Temperatures Aloft) выпускаются по фиксированному графику и охватывают станции по всей континентальной части США; этот эндпоинт возвращает все станции, координаты которых попадают в ваш ограничивающий прямоугольник (bounding box). Используйте его вместе с METAR и TAF, когда нужны составляющие ветра на крейсерской высоте для планирования топлива и времени, а не приземные условия в отдельном аэропорту. Покрытие — только США: запросы по территориям за пределами США возвращают 404 без станций.
Запрос
Требования
x-api-key в каждом запросе (прямая подписка). Подробнее →Отправьте GET с географическим ограничивающим прямоугольником. Необязательные query-параметры задают горизонт прогноза и диапазон высот.
https://data.skylinkapi.com/v3.1/weather/winds-aloft| Параметр | Тип | Обязательный | По умолчанию | Описание |
|---|---|---|---|---|
bbox | string | Да | - | Ограничивающий прямоугольник в формате lat1,lon1,lat2,lon2 — сначала юго-западный угол, затем северо-восточный. Пример: 40,-80,42,-73 (район Нью-Йорка) |
forecast | integer | Нет | 12 | Период прогноза в часах — 6, 12 или 24 |
level | string | Нет | low | Диапазон высот: low (3000–39 000 ft MSL) или high (6000–45 000 ft MSL) |
Советы по ограничивающему прямоугольнику. Держите прямоугольник как можно ближе к маршруту — меньшие области возвращают меньше станций, и ответ приходит быстрее. Координаты задаются в десятичных градусах (WGS-84). Долгота к западу от нулевого меридиана отрицательна (например, -73.78 для JFK).
Ответ
{
"bbox": "40.0,-80.0,42.0,-73.0",
"forecast_hour": 12,
"level": "low",
"valid_time": "131800Z",
"stations": [
{
"station": "JFK",
"latitude": 40.6413,
"longitude": -73.7781,
"winds": [
{
"altitude_ft": 3000,
"wind_direction": 310,
"wind_speed_kt": 7,
"temperature_c": null,
"light_and_variable": false,
"raw": "3107"
},
{
"altitude_ft": 18000,
"wind_direction": 270,
"wind_speed_kt": 35,
"temperature_c": -9,
"light_and_variable": false,
"raw": "2735-09"
}
],
"raw_text": "JFK 3107 3215+13 2926+08 2827+06 2735-09 2645-23 255637 256344 255852"
}
],
"total": 1
}| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
bbox | string | Да | Повтор запрошенного ограничивающего прямоугольника |
forecast_hour | integer | Да | Применённый период прогноза (6, 12 или 24) |
level | string | Да | Применённый диапазон высот (low или high) |
valid_time | string | null | Да (ключ присутствует всегда) | Время действия прогноза (UTC), например 131800Z. null, если не указано |
stations | array | Да | Станции FB Winds внутри bbox. [], если совпадений нет, — обычно вместе с 404 |
total | integer | Да | Количество станций в stations |
Диапазоны высот
level | Типичные возвращаемые высоты (ft MSL) |
|---|---|
low | 3000 / 6000 / 9000 / 12 000 / 18 000 / 24 000 / 30 000 / 34 000 / 39 000 |
high | 6000 / 9000 / 12 000 / 18 000 / 24 000 / 30 000 / 34 000 / 39 000 / 45 000 |
Точный набор высот для каждой станции зависит от продукта FB — не каждая станция возвращает все высоты.
Схемы объектов и допустимость null
Каждый ключ объекта станции присутствует всегда. Каждый ключ объекта уровня ветра присутствует всегда, если сам объект существует. Используйте null, 0 или [] согласно шаблонам ниже — никогда не проверяйте отсутствие ключа.
| Ситуация | Что вы получите | Чего не будет |
|---|---|---|
| Низкий уровень без температуры | temperature_c: null | 0, отсутствующий ключ |
| Группа ветра не декодирована | wind_direction: null, wind_speed_kt: null | отсутствующий ключ или 0 |
| Слабый ветер переменного направления | light_and_variable: true, wind_direction может быть null | null для light_and_variable |
| Станция без декодированных уровней | winds: [] | null, отсутствующий ключ |
| Нет исходной строки FB для станции | raw_text: null | отсутствующий ключ |
| Источник данных не указывает время действия | valid_time: null | отсутствующий ключ |
| Нет станций внутри bbox | stations: [] + HTTP 404 | null |
Схемы станции и уровня ветраРазвернуть раздел
Станция
Путь в JSON: stations[]. Каждый элемент представляет одну станцию FB Winds внутри bbox.
| Поле | Тип | Обязательный | Допускает null | Описание |
|---|---|---|---|---|
station | string | Да | Никогда | 3-буквенный идентификатор станции FB Winds (часто совпадает с ближайшим аэропортом, например JFK) |
latitude | number | Да | Никогда | Широта станции (десятичные градусы) |
longitude | number | Да | Никогда | Долгота станции (десятичные градусы) |
winds | array | Да | Никогда | Уровни ветра и температуры для этой станции. [], если ни один уровень не декодирован |
raw_text | string | null | Да (ключ присутствует всегда) | Да | Полная исходная строка FB Winds для этой станции. null, если не указана |
Уровень ветра
Путь в JSON: stations[].winds[]. Каждый элемент представляет один уровень высоты для родительской станции.
| Поле | Тип | Обязательный | Допускает null | Описание |
|---|---|---|---|---|
altitude_ft | integer | Да | Никогда | Высота уровня в футах над MSL |
wind_direction | integer | null | Да (ключ присутствует всегда) | Да | Истинное направление в градусах (0–360). null, если не декодировано |
wind_speed_kt | integer | null | Да (ключ присутствует всегда) | Да | Скорость в узлах. null, если не декодирована |
temperature_c | integer | null | Да (ключ присутствует всегда) | Да | Температура в °C. На самых низких уровнях (3000–6000 ft) часто null |
light_and_variable | boolean | Да | Никогда | true, если ветер слабый и переменного направления (< 5 kt). По умолчанию false |
raw | string | Да | Никогда | Закодированная группа ветра для этого уровня, например 2735-09 (270°/35 kt, −9 °C) |
Слабый ветер переменного направления. Когда light_and_variable равно true, скорость ветра ниже 5 узлов и определённого направления нет — wind_direction и wind_speed_kt могут быть null или нулём.
Клиентские типы
"""Winds aloft response types - matches winds-aloft field tables."""from dataclasses import dataclassfrom typing import Literal@dataclassclass WindLevel: altitude_ft: int wind_direction: int | None wind_speed_kt: int | None temperature_c: int | None light_and_variable: bool raw: str@dataclassclass WindsAloftStation: station: str latitude: float longitude: float winds: list[WindLevel] raw_text: str | None@dataclassclass WindsAloftResponse: bbox: str forecast_hour: int level: str valid_time: str | None stations: list[WindsAloftStation] total: int@dataclassclass CruiseWindSummary: station: str altitude_ft: int direction_deg: int | None speed_kt: int | None temperature_c: int | NoneИнтеграция
Запросите ветер для ограничивающего прямоугольника маршрута и выберите уровень, ближайший к планируемой крейсерской высоте.
Пример запрашивает прямоугольник вокруг района Нью-Йорка, кэширует ответ на один час (продукты FB обновляются по фиксированному графику) и возвращает уровень ветра, ближайший к целевой высоте. При 404 вспомогательная функция возвращает null, и вызывающий код показывает пустое состояние вместо ошибки.
import osimport timefrom typing import TypedDictimport requests# CruiseWindSummary - helper return type. Full wire types are in the Client types section.class WindLevel(TypedDict): altitude_ft: int wind_direction: int | None wind_speed_kt: int | None temperature_c: int | None light_and_variable: bool raw: strclass Station(TypedDict): station: str latitude: float longitude: float winds: list[WindLevel] raw_text: str | Noneclass WindsAloftResponse(TypedDict): bbox: str forecast_hour: int level: str valid_time: str | None stations: list[Station] total: intclass CruiseWindSummary(TypedDict): station: str altitude_ft: int direction_deg: int | None speed_kt: int | None temperature_c: int | NoneHEADERS = { "x-api-key": os.getenv("SKYLINK_API_KEY", "YOUR_API_KEY")}BASE = "https://data.skylinkapi.com/v3.1"CACHE: dict[str, tuple[WindsAloftResponse, float]] = {}WINDS_TTL = 3600 # 1 h - FB products update on a fixed scheduledef fetch_winds_aloft(bbox: str, forecast: int = 12, level: str = "low") -> WindsAloftResponse | None: cache_key = f"winds:{bbox}:{forecast}:{level}" cached = CACHE.get(cache_key) if cached and time.time() < cached[1]: return cached[0] try: r = requests.get( f"{BASE}/weather/winds-aloft", headers=HEADERS, params={"bbox": bbox, "forecast": forecast, "level": level}, timeout=(10, 20), ) except requests.Timeout as exc: raise RuntimeError(f"SkyLink timeout fetching winds aloft for {bbox}") from exc if r.status_code == 404: return None r.raise_for_status() data: WindsAloftResponse = r.json() CACHE[cache_key] = (data, time.time() + WINDS_TTL) return datadef nearest_cruise_wind( bbox: str, target_altitude_ft: int = 18_000, forecast: int = 12,) -> CruiseWindSummary | None: """Pick the wind level closest to target altitude from the first station in the bbox.""" payload = fetch_winds_aloft(bbox, forecast=forecast, level="low") if not payload or not payload["stations"]: return None station = payload["stations"][0] levels = station["winds"] if not levels: return None best = min(levels, key=lambda w: abs(w["altitude_ft"] - target_altitude_ft)) return { "station": station["station"], "altitude_ft": best["altitude_ft"], "direction_deg": best["wind_direction"], "speed_kt": best["wind_speed_kt"], "temperature_c": best["temperature_c"], }if __name__ == "__main__": import json from dataclasses import asdict bbox = "-74.5,40.3,-73.5,41.0" cruise = nearest_cruise_wind(bbox, target_altitude_ft=18_000) print(json.dumps(asdict(cruise), indent=2) if cruise else "No winds data")Примечания по реализации
Покрытие только США. FB Winds — продукт США. Bbox над Европой или океаном без станций США возвращает 404 — это не ошибка аутентификации или квоты. Стройте bbox по точкам маршрута в США.
Пустой результат и 404. Если ни один центроид станции не попадает в bbox, API возвращает 404 с сообщением detail, в котором указаны прогноз и уровень. Немного расширьте bbox или сместите его вдоль маршрута.
Выбор level. Используйте low для типичного крейсерского полёта авиалайнеров ниже FL390. Используйте high, когда нужны данные для FL390–FL450. Если сервис временно недоступен для уровня, вы можете получить 503 — повторите запрос с экспоненциальной задержкой (backoff).
Отсутствие температуры на низких высотах. На уровне 3000 ft, а иногда и 6000 ft температура обычно не указывается (temperature_c: null). Используйте для планирования направление и скорость ветра; отсутствующую температуру трактуйте как «не сообщается на этом уровне».
Ответы с ошибками
Здесь описаны только ошибки, специфичные для эндпоинта. Об ошибках аутентификации, валидации, ограничениях частоты запросов и ошибках сервера, общих для всех эндпоинтов, см. Обработка ошибок.
404 — в bbox нет станций
{
"detail": "No FB winds stations found in the given bounding box for forecast=12h, level=low"
}Частые причины: bbox за пределами покрытия США, слишком маленький bbox между станциями или координаты вне США. Расширьте прямоугольник или убедитесь, что маршрут проходит над США.
400 — некорректный формат bbox
{
"detail": "Invalid bounding box format. Expected 'lat1,lon1,lat2,lon2'"
}503 — источник данных недоступен
{
"detail": "Winds aloft service temporarily unavailable"
}Повторите запрос после короткой задержки. Если ошибка сохраняется, попробуйте другой level или другой час forecast.
Your SkyLink licence key, for keys bought direct from skylinkapi.com.
In: header
Query Parameters
Bounding box as 'lat1,lon1,lat2,lon2' (SW corner → NE corner)
Forecast period in hours (6, 12, or 24)
126 <= value <= 24Altitude range: 'low' (3K-39K ft) or 'high' (6K-45K ft)
"low"^(low|high)$Response Body
application/json
application/json
curl -X GET "https://data.skylinkapi.com/v3.1/weather/winds-aloft?bbox=string"{
"bbox": "40,-80,42,-73",
"forecast_hour": 12,
"level": "low",
"valid_time": "130000Z",
"stations": [
{
"station": "JFK",
"latitude": 40.6413,
"longitude": -73.7781,
"winds": [
{
"altitude_ft": 3000,
"wind_direction": 270,
"wind_speed_kt": 9,
"light_and_variable": false,
"raw": "2709"
}
],
"raw_text": "JFK 2709 3012+08 ..."
}
],
"total": 1
}{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string",
"input": null,
"ctx": {}
}
]
}См. также: Раздел «Погода» · METAR · TAF · Сценарий: ветер на крейсерской высоте
TAF
Прогнозы по аэродрому (TAF) для любого аэропорта ICAO. Опциональный декодированный вывод: периоды прогноза и ожидаемая категория полётных условий.
PIREP (донесения пилотов)
Донесения пилотов (PIREP) в ограничивающем прямоугольнике: турбулентность, обледенение и погода в полёте, переданные пилотами за заданный период.