你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
如何编写天气扩展
在本部分中,你将看到一个分步指南,指导你编写自己的天气扩展。
什么是天气扩展
Data Manager for Agriculture 中的天气扩展是一个清单 (JSON) 文件,它提供了 API 的完整详细信息,以及每个 API 响应(输出)的模板。 因此,扩展文件本质上是 Data Manager for Agriculture 定义的一个 API 模板结构,用于了解 API 输入(请求)和输出(响应)特征。
天气扩展结构
概括而言,扩展文件是一个 JSON,其中包含两项内容:
- 提供程序元数据(JSON 对象)
- API 信息(JSON 数组)
提供程序元数据
它是一个 JSON 对象,提供以下字段的详细信息,这些字段是唯一标识扩展及其版本控制信息所必需的。 扩展的此部分中提供的详细信息将在 Data Manager for Agriculture 市场中显示给外部客户。 因此,extensionId
和 extensionName
(方便识别)和 description
(用于价值主张)需要以客户为重点。
示例提供程序元数据
"provider": {
"extensionId": "abc.weather",
"extensionName": "ABC weather",
"description": "Get Weather data from ABC weather into Azure Data Manager for Agriculture platform using this extension",
"dataCategory": "Weather",
"farmBeatsSchemaVersion": "1.0",
"extensionVersion": "1.0",
"supportUrl": "www.abc.com/support",
"supportEmail": "support@abc.com"
}
提供程序元数据详细信息
名称 | Type | 描述 |
---|---|---|
extensionId | string | 以组织名称 (Contoso) 和服务 (weather) 的方式提供的 ID,例如:org.service 。 extensionId 是扩展的唯一标识符,也是用户在 Data Manager for Agriculture 平台上用来与扩展 API 交互的标识符 |
extensionName | string | Data Manager for Agriculture 扩展市场中使用的扩展名称。 |
description | string | 说明,陈述了扩展提供的功能和服务。 |
dataCategory | string | 对于天气扩展,请使用 weather 。 |
farmBeatsSchemaVersion | string | Data Manager for Agriculture 端的清单文件的版本。 对现有清单文件的任何更新都会导致对此字段进行新版本更新。 |
extensionVersion | string | 扩展文件的版本。 从 1.0 开始。 对扩展文件的更新会根据主要和次要更新的约定递增此版本号。 |
支持 URL | string | 用于提交支持问题并提供常见问题解答的网站链接 |
supportEmail | string | 要在支持查询中发送的电子邮件。 |
API 信息
API 信息 JSON 数组 (apiInfos
) 可以进一步分解为以下结构元素。
- API 元数据
- 身份验证参数
- API 输入参数
- 提取的 API 输入参数
- 功能参数
- 单位系统
- 平台和自定义参数
- 平台和自定义模板
API 元数据
此部分包含有关 Data Manager for Agriculture 用于识别 apiName
(由用户显式调用)的 API,以及根据适当的 requestType
将 API 请求重定向到正确 endpoint
的基本信息。
API 元数据示例
"apiInfos": [
{
"apiName": "dailyforecast",
"description": "The Daily Forecast API",
"endpoint": "https://ag.us.clearapis.com/v1.1/forecast/daily",
"requestType": "GET",
"isLoadAPI": "false",
"typeOfData": "forecast",
"granularity": "daily",
"defaultUnitSystem": "us"
}
]
API 元数据详细信息
名称 | Type | 描述 |
---|---|---|
apiInfos | array | 对象的 JSON 数组,其中每个 API 都是 apiInfos 数组中的一个对象。 |
apiName | string | 扩展支持的 API 名称,它是用户将用来调用扩展 API 的确切名称。 请遵循 API 文档中提到的相同命名约定。 |
description | string | API 说明 |
endpoint | string | Data Manager for Agriculture 用于调用 apiName 的 API 终结点。 |
requestType | string | apiName 支持的 GET 、POST 或 PUT 请求类型。 |
isLoadAPI | boolean | 如果 apiName 是一个直通 API(例如当前天气数据),请将此键设为 false 。 对于所有负载 API(历史和预测),请将此字段保留为 true 。 当 isLoadAPI 键为 false 时,API 响应将直接发送给用户,并且不会存储在 Data Manager for Agriculture 存储服务中。 |
typeOfData | string | 当前支持的值为 Historical 和 Forecast 。 |
粒度 | string | 当前支持的值为 Daily 和 Hourly 。 |
defaultUnitSystem | string | 提供 apiName 支持的默认单位系统的名称。 |
身份验证参数
此部分采用 apiName
支持的身份验证相关参数。 由于 Data Manager for Agriculture 在 API 标头部分中支持两种类型的身份验证相关密钥(x-ms-farmBeats-data-provider-id
和 x-ms-farmBeats-data-provider-key
),因此扩展文件需要根据 apiName
的要求显式提供其各自身份验证密钥的密钥名称。
Data Manager for Agriculture 通过 API 标头收集身份验证信息(在创建天气作业 API 中)。 因此,将会进行身份验证参数映射来确保 Data Manager for Agriculture 可以根据要求相应地将密钥传递给扩展。
身份验证参数示例
"apiInfos": [
"authInputParameters": [
{
"farmBeatsAuthMapping": "x-ms-farmBeats-data-provider-id",
"name": "app_id",
"isRequired": "true",
"providerDataType": "string",
"description": "Provide the APP ID, username etc. that your API supports",
"location": "apiQuery"
},
{
"farmBeatsAuthMapping": "x-ms-farmBeats-data-provider-key",
"name": "app_key",
"isRequired": "true",
"providerDataType": "string",
"description": "Provide the API Key or password etc. that your API supports",
"location": "apiQuery"
}
]
]
身份验证参数详细信息
名称 | Type | 描述 |
---|---|---|
authInputParameters | array | 身份验证参数的 JSON 数组,其中每个对象都表示一个受支持的身份验证类型。 请根据你的扩展支持的身份验证类型使用此键。 |
farmBeatsAuthMapping | string | 目前支持两种类型的身份验证相关密钥。 对于基于 API 密钥的身份验证,请仅使用 x-ms-farmBeats-data-provider-key 对象,而对于基于应用 ID 和基于应用密钥的身份验证,请同时使用 x-ms-farmBeats-data-provider-id 和 x-ms-farmBeats-data-provider-key 对象。 |
name | string | apiName 支持的身份验证密钥的名称。 |
IsRequired | boolean | 此名称是否为 apiName 的必需参数? 请提供 true 或 false 值。 |
providerDataType | string | 提供 name 参数的数据类型。 |
description | string | Data Manager for Agriculture 对每个 farmBeatsAuthMapping 在每个对象中的含义的说明。 |
location | string | 应在 API 中的哪个位置发送 name 参数。 当前支持的值为 apiQuery 和 apiHeader 。 |
API 输入参数
此部分提供有关成功调用 apiName
的 API 签名(输入参数)的详细信息。
API 输入参数示例
"apiInfos": [
"apiInputParameters": [
{
"name": "start",
"isRequired": "true",
"providerDataType": "double",
"description": "Start of time range. Valid start values range from zero to nine. Day zero represents the current day.",
"location": "apiQuery"
},
{
"name": "end",
"isRequired": "true",
"providerDataType": "double",
"description": "End of time range. Valid end values range from zero to nine.",
"location": "apiQuery"
},
{
"name": "location",
"isRequired": "true",
"providerDataType": "string",
"description": "User-provided latitude and longitude coordinates. Formatted as location=[(<lat_1>,<lon_1>)].",
"location": "apiQuery"
},
{
"name": "unitcode",
"isRequired": "false",
"providerDataType": "string",
"description": "Unit conversion set to be used. Default is us-std. Valid values are us-std, si-std.",
"location": "apiQuery"
},
]
]
API 输入参数详细信息
名称 | Type | 描述 |
---|---|---|
apiInputParameters | array | API 输入参数的 JSON 数组,其中每个对象都表示 apiName 支持的一个输入参数。 |
name | string | apiName 支持的输入参数的名称。 |
IsRequired | boolean | 此名称是否为 apiName 的必需参数? 请提供 true 或 false 值。 |
providerDataType | string | 提供 name 参数的数据类型。 |
description | string | 提供 name 参数含义的说明。 |
location | string | 应在 API 中的哪个位置发送 name 参数。 当前支持的值为 apiQuery 和 apiHeader 。 |
提取的 API 输入参数
此部分是有关 Data Manager 提取在 API 请求中传递的用于计算和存储的输入参数的信息。 在此示例中,Data Manager for Agriculture 将从 API 输入请求中提取位置信息(纬度和经度),并将其存储为 Data Manager for Agriculture 中每个天气输出的一部分。
因此,扩展需要提供有关如何提取位置信息的 HandleBars 模板。 下面的示例建议扩展 API 将位置信息收集为 "lat"
(对于 "latitude"
)和 "lon"
(对于 "longitude"
)。
提取的 API 输入参数示例
"extractedApiInputParameters": [
{
"name": "location",
"template": "{ \"latitude\": \"{{lat}}\", \"longitude\": \"{{lon}}\" } "
}
]
提取的 API 输入参数详细信息
名称 | Type | 描述 |
---|---|---|
extractedApiInputParameters | array | 提取功能的 JSON 数组,其中每个对象都表示需要提取的信息。 当前,location 就是一个这样的提取。 |
name | string | 提取的名称,当前支持的值为 location 。 |
template | string | HandleBars 模板,描述如何在 API 输入参数中收集纬度和经度信息。 |
功能参数
此部分专用于由 Data Manager for Agriculture 构建的功能。 对于天气扩展,质心计算是这样的功能之一。
当用户未提供纬度/经度坐标时,Data Manager for Agriculture 使用该字段的主要几何图形(用户传递的 ID)来计算质心。 算出的质心坐标作为纬度和经度传递给扩展(数据提供程序)。 因此,为了使 Data Manager for Agriculture 能够理解位置坐标的用法,使用了功能参数部分。
为了使 Data Manager for Agriculture 理解 apiName
输入参数中纬度和经度的用法,扩展应提供用于收集位置信息的键的 name
,后跟一个 handlebar 模板来指明需要如何传递纬度和经度值。
功能参数示例
"apiInfos": [
"functionalParameters": [
{
"name": "CentroidCalculation",
"description": "Provide names of the parameters used to collect latitude and longitude information",
"functionalParameterEntities": [
{
"name": "lat",
"template": "{ \"lat\": \"{{latitude}}\" } "
},
{
"name": "lon",
"template": "{ \"lon\": \"{{longitude}}\" } "
}
]
}
],
]
功能参数详细信息
名称 | Type | 描述 |
---|---|---|
functionalParameters | array | 功能的 JSON 数组,其中每个对象都表示 Data Manager for Agriculture 支持的一个功能。 当前,CentroidCalculation 就是一个这样的功能。 |
name | string | 功能的名称,当前支持的值为 CentroidCalculation 。 |
description | string | Data Manager for Agriculture 对功能的说明。 |
functionalParameterEntities | array | 对象的 JSON 数组,其中每个对象都特定于纬度和经度。 |
单位系统
此部分供 Data Manager for Agriculture 用来理解扩展支持的各种类型的单位系统。 因此,扩展需要提供用于在 API 输入中收集单位信息的 key
名称,后跟 apiName
支持的各种单位系统名称(例如:us-std)。
单位系统示例
"unitSystems":
{
"key": "unitcode",
"values": [
"us-std",
"si-std",
"us-std-precise",
"si-std-precise"
]
}
单位系统详细信息
名称 | Type | 描述 |
---|---|---|
unitSystems | object | 用于收集单位系统信息的 JSON 对象。 |
键 | string | 用于收集 API 输入中的单位信息的参数的名称。 |
值 | string | 扩展支持的单位系统名称的列表。 |
平台和自定义参数
在每个天气 API 响应中,作为输出的一部分发送的天气度量值(例如:温度、露点,等等)称为参数。
因此,在参数方面,Data Manager for Agriculture 在内部支持下列一组参数,并将其视为 Platform parameters
。
- cloudCover
- dateTime
- dewPoint
- growingDegreeDay
- precipitation
- pressure
- relativeHumidity
- soilMoisture
- soilTemperature
- 温度
- 可见性
- wetBulbTemperature
- windChill
- windDirection
- windGust
- windSpeed
因此,在发送不属于平台参数的天气参数时,任何扩展都会将其作为 Custom parameters
的一部分发送。 平台参数与自定义参数之间的主要区别在于,使用 Data Manager for Agriculture 天气 API 的用户能够基于平台参数进行查询和筛选(例如:温度 > 30),但不能基于自定义参数进行查询和筛选。 但是,自定义参数作为天气查询输出的一部分发送。
在此部分中,扩展为受支持的每个单位系统提供每个参数的单位信息。 使用此部分,Data Manager for Agriculture 可以根据扩展的此部分中提供的信息了解每个天气参数的基本测量单位。
注意
- 对于特定参数,如果单位不适用,则不要单独提及这些参数的单位(例如:weatherDescriptor)
- 对于特定参数,如果单位在所有单位系统中都相同,则在所有单位系统中提及该相同的单位。 (例如:cloudCover)
平台和自定义参数示例
"apiInfos": [
"platformParameters": [
{
"farmBeatsName": "cloudCover",
"farmBeatsDataType": "double",
"description": "The average percentage of sky covered by clouds.",
"measurementUnits": [
{
"unitSystem": "us-std",
"unit": "%"
},
{
"unitSystem": "us-std-precise",
"unit": "%"
},
{
"unitSystem": "si-std",
"unit": "%"
},
{
"unitSystem": "si-std-precise",
"unit": "%"
}
]
},
{
"farmBeatsName": "dewPoint",
"farmBeatsDataType": "double",
"description": "The air temperature at which the air will become saturated, and dew moisture will condense into fog (or dew).",
"measurementUnits": [
{
"unitSystem": "us-std",
"unit": "F"
},
{
"unitSystem": "us-std-precise",
"unit": "F"
},
{
"unitSystem": "si-std",
"unit": "C"
},
{
"unitSystem": "si-std-precise",
"unit": "C"
}
]
},
"customParameters": [
{
"providerName": "weatherDescriptor",
"providerDataType": "string",
"description": "General weather descriptor data"
},
{
"providerName": "airTempMax",
"providerDataType": "double",
"description": "Maximum daily air temperature at two meters above ground level.",
"measurementUnits": [
{
"unitSystem": "us-std",
"unit": "F"
},
{
"unitSystem": "us-std-precise",
"unit": "F"
},
{
"unitSystem": "si-std",
"unit": "C"
},
{
"unitSystem": "si-std-precise",
"unit": "C"
}
]
},
]
平台参数详细信息
名称 | Type | 描述 |
---|---|---|
platformParameters | array | 平台参数的 JSON 数组,其中每个对象都是一个平台参数。 |
farmBeatsName | string | Data Manager for Agriculture 提供的参数名称。 |
farmBeatsDataType | string | Data Manager for Agriculture 提供的参数数据类型。 |
description | string | Data Manager for Agriculture 提供的参数说明。 |
measurementUnits | string | 扩展支持的每个单位系统 values 的单位的 JSON 数组。 |
unitSystem | string | 扩展支持的单位系统 value 。 |
unit | string | 特定天气参数的度量单位,例如:用于 dewPoint 的 F 。 |
自定义参数详细信息
名称 | Type | 描述 |
---|---|---|
customParameters | object | 自定义参数的 JSON 数组,其中每个对象都是一个自定义参数。 |
providerName | string | 扩展提供的参数名称。 |
providerDataType | string | 扩展提供的参数数据类型。 |
description | string | 扩展提供的参数说明。 |
measurementUnits | string | 扩展支持的每个单位系统 values 的单位的 JSON 数组。 |
unitSystem | string | 扩展支持的单位系统 value 。 |
unit | string | 特定天气参数的度量单位,例如:用于 airTempMax 的 F 。 |
平台和自定义模板
模板是扩展提供的映射信息,用于将扩展 API 输出(JSON 响应)转换为 Data Manager for Agriculture 预期的格式。 使用此模板,现在可以将不同的 API 输出格式统一映射/转换为一种格式。
模板解决方案是用来分析由扩展提供的 JSON 输出的最有效方法之一。 对于天气扩展,Data Manager for Agriculture 预期使用 HandleBars 模板来编写扩展。 HandleBars 是一种开源模板化语言,采用易于使用的表达式。
注意
强烈建议使用提供的示例来试用 HandleBars 模板,并了解如何使用帮助程序函数来构建自己的解析逻辑(如果 Data Manager for Agriculture 尚未提供)。
概括而言,这是模板的工作方式,即接受 API 响应作为输入,并以 Data Manager for Agriculture 预期的格式生成输出。
如上图所示,根据相应的 API 响应验证你的模板,并在扩展中使用已验证的模板。 下面是一个 API 响应及其相应的平台和自定义模板的示例。
API 响应示例
{
"47,-97": {
"2016-12-15": {
"overall": {
"air_temp_avg": {
"unit": "F",
"value": -3.0
},
"air_temp_max": {
"unit": "F",
"value": 5.0
},
"air_temp_min": {
"unit": "F",
"value": -11.0
},
"cloud_cover_avg": {
"unit": "%",
"value": 26.4
},
"descriptors": {
"cloud_cover_descriptor": {
"code": 21107,
"icon": "https://.../cover_partlycloudyday.png",
"text": "Increasing Clouds"
},
"precipitation_descriptor": {
"code": 61113,
"icon": "https://.../precip_flurries.png",
"text": "Slight Chance of Flurries"
},
"weather_descriptor": {
"code": 61113,
"icon": "https://.../precip_flurries.png",
"text": "Slight Chance of Flurries"
},
"wind_direction_descriptor": {
"code": 51600,
"icon": "https://.../direction_sw.png",
"text": "Southwest"
},
"wind_trend_descriptor": {
"code": 10500,
"icon": "https://.../error_none.png",
"text": "None"
}
},
"dew_point_avg": {
"unit": "F",
"value": -11.0
},
"dew_point_max": {
"unit": "F",
"value": -4.0
},
"dew_point_min": {
"unit": "F",
"value": -19.0
},
"ice_acc_period": {
"unit": "in",
"value": 0.0
},
"liquid_acc_period": {
"unit": "in",
"value": 0.0
},
"long_wave_radiation_avg": {
"unit": "W/m^2",
"value": 170.0
},
"pet_period": {
"unit": "in",
"value": 0.009
},
"precip_acc_period": {
"unit": "in",
"value": 0.001
},
"precip_prob": {
"unit": "%",
"value": 10.0
},
"relative_humidity_avg": {
"unit": "%",
"value": 68.0
},
"relative_humidity_max": {
"unit": "%",
"value": 77.0
},
"relative_humidity_min": {
"unit": "%",
"value": 61.0
},
"short_wave_radiation_avg": {
"unit": "W/m^2",
"value": 70.0
},
"snow_acc_period": {
"unit": "in",
"value": 0.02
},
"sunshine_duration": {
"unit": "hours",
"value": 6
},
"wind_gust_max": {
"unit": "n/a",
"value": "n/a"
},
"wind_speed_2m_avg": {
"unit": "mph",
"value": 6.0
},
"wind_speed_2m_max": {
"unit": "mph",
"value": 8.0
},
"wind_speed_2m_min": {
"unit": "mph",
"value": 2.0
},
"wind_speed_avg": {
"unit": "mph",
"value": 8.0
},
"wind_speed_max": {
"unit": "mph",
"value": 11.0
},
"wind_speed_min": {
"unit": "mph",
"value": 3.0
}
}
}
}
}
上面的 API 响应的平台和自定义模板示例
{
"apiInfos": {
"platformTemplate": "{ {{#each .}}\"value\": [{{#each .}} {\"cloudCover\": \"{{overall.cloud_cover_avg.value}}\" ,\"dewPoint\": \"{{overall.dew_point_avg.value}}\" ,\"precipitation\": \"{{overall.precip_acc_period.value}}\" ,\"relativeHumidity\": \"{{overall.relative_humidity_avg.value}}\" ,\"dateTime\": \"{{convertDateInYYYYMMDDToDateTime @key}}\", \"temperature\": \"{{overall.air_temp_avg.value}}\" ,\"windSpeed\": \"{{overall.wind_speed_avg.value}}\" , },{{/each}}]{{/each}} }",
"customTemplate": "{ {{#each .}}\"value\": [{{#each .}} {\"air_temp_max\": \"{{overall.air_temp_max.value}}\",\"air_temp_min\": \"{{overall.air_temp_min.value}}\",\"cloudCoverDescriptor\": \"{{overall.descriptors.cloud_cover_descriptor.text}}\",\"precipitationDescriptor\": \"{{overall.descriptors.precipitation_descriptor.text}}\",\"weatherDescriptor\": \"{{overall.descriptors.weather_descriptor.text}}\",\"windDirectionDescriptor\": \"{{overall.descriptors.wind_direction_descriptor.text}}\",\"windTrendDescriptor\": \"{{overall.descriptors.wind_trend_descriptor.text}}\",\"dewPointMax\": \"{{overall.dew_point_max.value}}\",\"dewPointMin\": \"{{overall.dew_point_min.value}}\",\"iceAccPeriod\": \"{{overall.ice_acc_period.value}}\",\"liquidAccPeriod\": \"{{overall.liquid_acc_period.value}}\",\"longWaveRadiationAvg\": \"{{overall.long_wave_radiation_avg.value}}\",\"petPeriod\": \"{{overall.pet_period.value}}\",\"precipProb\": \"{{overall.precip_prob.value}}\",\"relativeHumidityMax\": \"{{overall.relative_humidity_max.value}}\",\"relativeHumidityMin\": \"{{overall.relative_humidity_min.value}}\",\"shortWaveRadiationAvg\": \"{{overall.short_wave_radiation_avg.value}}\",\"snowAccPeriod\": \"{{overall.snow_acc_period.value}}\",\"sunshineDuration\": \"{{overall.sunshine_duration.value}}\",\"windSpeed2mAvg\": \"{{overall.wind_speed_2m_avg.value}}\",\"windSpeed2mMax\": \"{{overall.wind_speed_2m_max.value}}\",\"windSpeed2mMin\": \"{{overall.wind_speed_2m_min.value}}\",\"windSpeedMax\": \"{{overall.wind_speed_max.value}}\",\"windSpeedMin\": \"{{overall.wind_speed_min.value}}\",},{{/each}}]{{/each}} }"
}
}
注意
从 HandleBars 生成的模板通过添加 \"<text>\"
进行字符串化,使其与 JSON 格式兼容。
帮助函数
模板使用帮助程序函数对原本不受支持的数据执行特定转换。 下面是 Data Manager for Agriculture 支持的帮助程序函数。
帮助程序函数示例
Handlebars.registerHelper('splitAndTake', function(title, char, index) {
var t = title.split(char);
return t[index];
});
Handlebars.registerHelper('converttime', function(timestamp) {
return new Date(timestamp);
});
Handlebars.registerHelper('convertunixtime', function(unix_timestamp) {
return new Date(unix_timestamp * 1000);
});
这些帮助程序函数的作用是什么?
- SplitAndTake(object valueObject, string separator, int index) - 此函数用于基于分隔符(例如:",")来拆分字符串(例如:"47,-97"),并获取给定索引处的元素(例如:索引为 0 时将得到 "47")
- ConvertDateInFormatToDateTime(object dateObject, string format) - 此函数用于将给定格式的日期(例如:2016-12-15)转换为日期/时间字符串。
- ConvertUnixTimeToDateTime(object unixTimeStamp) - 此函数用于将 unix 时间戳(例如:1392267600)转换为日期/时间字符串。
- GetObjectFromListWithKeyValuePair(Array listOfObjects, string key, string value) -给定对象列表时,它根据键 (
type
) 值 (RAIN
) 对提取对象。 在下面的示例中,若要选取"type": "RAIN"
降水量,将使用此函数。
{
"precipitation": [
{
"type": "SNOW",
"amount": 0
},
{
"type": "RAIN",
"amount": 0.01
}
]
}
- GetValueFromObject(string jsonString, string key) - 以字符串形式给定 json 对象时,它将基于键获取值。
注意
如果要编写的扩展需要其他帮助程序函数来分析 API 响应,请通过创建支持工单联系我们。