Open-Meteo 天气 API 使用 FlatBuffers 高效地编码 API 响应。各种编程语言的已编译架构文件可以在此存储库中找到。
FlatBuffers 的最大优势在于,大型浮点数组可以直接编码,而无需进行昂贵的 JSON ASCII 转换。特别是对于历史天气数据,处理速度明显更快。而且,即使在低功耗设备上显示常规天气预报,二进制数据编码也能节省能源。
FlatBuffers 架构定义可以在 ./flatbuffers 目录中找到。仅接受非破坏性更改。二进制兼容性得到保证。每个更改都将在遵循语义版本控制的新版本中宣布。
已编译的架构文件不包含任何执行 HTTP 调用的代码。它们旨在供开发人员构建客户端库使用。
有关如何使用已编译架构文件的更多信息,可以在每种编程语言的目录中找到
并非所有编程语言都已支持。验证所有语言是一个耗时的过程。请打开 issue 工单,询问是否支持其他语言和/或软件包分发系统。
Open-Meteo 提供各种 API。每个 API 端点都使用不同的 FlatBuffers 架构来编码其 API 响应。这实现了严格的类型化。例如,天气数据 API 提供不同的变量,而地理编码 API 返回不同的结构。默认情况下,Open-Meteo API 返回 JSON,但在 URL 中指定 &format=flatbuffers 将返回 FlatBuffers 编码的数据。
根据编程语言,您可以使用 HTTP 客户端获取所有数据,并根据每个 API 端点解码响应。以下 API 响应架构文件可用
每个响应包含一个位置和一个天气模型的数据。如果请求多个位置,则将返回多个 ApiResponses 作为使用 size-prefixed 编码(见下文)的数组。
主要的 WeatherApiResponse 结构包含
latitude & longitude float: 天气模型网格单元的坐标elevation float: 请求坐标的地形海拔generation_time_milliseconds floatlocation_id int64: 位置标识符model Model: 天气模型名称,作为枚举utc_offset_seconds int32: 与 GMT 时间的时区偏移量,以秒为单位。例如 3600timezone string: 时区名称,例如 Europe/Berlintimezone_abbreviation string: 缩写,例如 CETcurrent VariablesWithTime: 所有使用 ¤t= 请求的变量daily VariablesWithTime: 所有使用 &daily= 请求的变量hourly VariablesWithTime: 所有使用 &hourly= 请求的变量minutely_15 VariablesWithTime: 所有使用 &minutely_15= 请求的变量six_hourly VariablesWithTime: 所有使用 &six_hourly= 请求的变量所有 hourly 或 daily 天气变量都分组到 VariablesWithTime 类中。它包含开始和结束时间以及间隔。
属性
start int64: GMT 中第一个值的 Unix 时间戳end int64: 不包含在时间间隔内的最后一个时间戳。因此,是最后一个包含的时间步之后的一步。interval int32: 每个步长的秒数。对于每小时数据,这是 3600 秒,对于每日数据,这是 86400 秒。variables [VariableWithValues]: 天气变量数组时间戳始终使用 Unix 时间(秒)。时间始终为 GMT!如果您想再次显示本地时间,可以使用响应结构中的属性 utc_offset_seconds
每个天气变量都附带元数据,例如天气变量的名称或单位。
属性
variable Variable: 天气变量的枚举。例如 temperature(温度)unit Unit: 结果使用的单位。例如 celsius(摄氏度)value float: 对于 current 值,数据存储在此字段中values [float]: 任何其他时间序列数据都作为浮点数组存储在此处values_int64 [int64]: 变量 sunrise(日出) 和 sunset(日落) 使用此字段将数据存储为 Unix 时间戳altitude int16: 给定变量的高度。例如,2 米处温度为 2,10 米处风速为 10aggregation Aggregation: 每日变量的聚合类型,例如 minimum(最小值)、mean(平均值) 或 maximum(最大值)pressure_level int16: 如果请求较高大气层中的天气变量,则此字段包含压力水平,单位为百帕斯卡。例如 850 表示 850 hPa。depth int16: 对于土壤变量,这定义了上限。例如 soil_moisture_7_to_28 中的 7depth_to int16: 下限。例如 soil_moisture_7_to_28 中的 28ensemble_member int16: 对于集合数据,此处设置每个集合的成员。0 通常是控制运行。Model 枚举包含所有可用的模型,例如 icon_global 或 best_match。
根据编程语言,您将需要解码模型以获得可用的字符串。例如,对于 Python
from openmeteo_sdk import Model
def model_to_name(code):
"""convert Model to name"""
for name, value in Model.Model.__dict__.items():
if value == code:
return name
return None
print(response.Model()) # 1
print(model_to_name(result.Model())) # "best_match"
Variable 枚举包含所有可用的变量,例如 temperature(温度) 或 wind_speed(风速)。请注意,高度不包含在变量名称中。temperature_2m 编码为 variable=temperature 和 altitude=2。
Unit 枚举包含所有可用的单位,例如 celsius(摄氏度) 或 metre_per_second(米/秒)。
Aggregation 枚举包含每日变量的所有聚合类型,例如 minimum(最小值) 或 maximum(最大值)。
多个天气变量编码为列表。如果要访问单个变量,您将需要循环遍历数组,并按变量名称和高度进行过滤。这是一个获取 temperature_2m(2 米温度) 和 precipitation(降水) 的示例。
from openmeteo_sdk.Variable import Variable
response = ...
hourly = response.Hourly()
hourly_variables = list(map(lambda i: hourly.Variables(i), range(0, hourly.VariablesLength())))
temperature_2m = next(filter(lambda x: x.Variable() == Variable.temperature and x.Altitude() == 2, hourly_variables))
precipitation = next(filter(lambda x: x.Variable() == Variable.precipitation, hourly_variables))
print(temperature_2m.ValuesAsNumpy())
print(precipitation.ValuesAsNumpy())
根据变量的不同,您只需按变量名称进行过滤。如果您选择多个高度的风速,例如 wind_speed_10m(10 米风速) 和 wind_speed_80m(80 米风速),则按 altitude(高度) 过滤是相关的。
如果您选择不同的每日聚合,请确保也检查正确的聚合。示例
from openmeteo_sdk.Variable import Variable
from openmeteo_sdk.Aggregation import Aggregation
daily = response.Daily()
daily_variables = list(map(lambda i: daily.Variables(i), range(0, daily.VariablesLength())))
temperature_2m_max = next(filter(lambda x: x.Variable() == Variable.temperature and x.Altitude() == 2 and x.Aggregation() == Aggregation.maximum, daily_variables))
temperature_2m_min = next(filter(lambda x: x.Variable() == Variable.temperature and x.Altitude() == 2 and x.Aggregation() == Aggregation.minimum, daily_variables))
print(temperature_2m_max.ValuesAsNumpy())
print(temperature_2m_min.ValuesAsNumpy())
请求变量的顺序将被保留。例如 ¤t=temperature_2m,wind_speed_10m,weather_code 将完全保持此顺序。因此,您可以直接使用索引。注意:current 仅返回一个变量,编码到 value 字段中。
current = response.Current()
timestamp = current.start()
temperature_2m = current.Variables(0).value()
wind_speed_10m = current.Variables(1).value()
weather_code = current.Variables(2).value()
可以在一个 API 调用中请求多个位置和多个天气模型的数据。例如 &latitude=47.1,49.7&longitude=8.6,9.4。要一次返回多个位置,将发送多个 FlatBuffers 消息。
为了区分多个消息,每个消息都以其长度作为 32 位整数(小端字节序)作为前缀。这被称为 size-prefixed FlatBuffer 消息。在线传输的消息看起来像这样
在解码响应时,您可以循环遍历数据并逐个处理。作为参考,这是 Python 代码。
一次最多可以请求 1000 个位置。Open-Meteo API 预取所有位置的数据,但将逐个位置处理并“流式传输”响应。因此,可以在服务器仍在处理后续消息时解码第一个消息。这对于摄取大量数据可能很有用,但这是一个相当复杂的方法。为了简单起见,等待整个响应然后开始处理数据也效果很好。
如果您想检查 Open-Meteo API 以二进制 FlatBuffers 格式返回的数据,可以使用 FlatBuffers 架构编译器 flatc。这可以帮助理解 API 响应的结构。
首先,您需要安装 FlatBuffers 编译器。Mac: brew install flatbuffers。Ubuntu sudo apt install flatbuffers-compiler。
从该存储库获取 weather_api.fbs。
# Make sure the URL contains `&format=flatbuffers`
wget -O data.bin https://api.open-meteo.com/v1/forecast\?latitude\=52.52\&longitude\=13.41\&daily\=weather_code,temperature_2m_max,temperature_2m_min\&timezone\=auto\&format\=flatbuffers
flatc --json --size-prefixed --raw-binary weather_api.fbs -- data.bin
cat data.json
{
latitude: 52.52,
longitude: 13.419998,
elevation: 38.0,
generation_time_milliseconds: 0.247002,
model: "best_match",
utc_offset_seconds: 3600,
timezone: "Europe/Berlin",
timezone_abbreviation: "CET",
daily: {
time: 1698620400,
time_end: 1699225200,
interval: 86400,
variables: [
{
variable: "weather_code",
unit: "wmo_code",
values: [
3.0,
80.0,
3.0,
61.0,
61.0,
61.0,
61.0
]
},
{
variable: "temperature",
unit: "celsius",
values: [
14.8455,
12.7955,
14.0455,
13.938999,
12.389,
12.3695,
14.4695
],
altitude: 2,
aggregation: "maximum"
},
{
variable: "temperature",
unit: "celsius",
values: [
11.1455,
8.1455,
7.4955,
8.488999,
8.188999,
6.389,
9.0195
],
altitude: 2,
aggregation: "minimum"
}
]
}
}
注意:model(模型)、variable(变量)、unit(单位) 和 aggregation(聚合) 的值被编码为枚举,枚举使用整数而不是字符串。只有 timezone(时区) 和 timezone_abbreviation(时区缩写) 是实际的字符串,它们在二进制 API 响应中进行编码。
MIT