预警 API
单点查询 API
TIP
目前支持中国、日本的气象预警信息,其他国家和地区的预警信息正在逐步增加中。
每次调用消耗接口调用额度一次。
bash
curl "https://singer.caiyunhub.com/v3/alert/location?token=token&longitude=113.31685980902778&latitude=23.1251321072048"
请求参数:
Field | Type | Description |
---|---|---|
longitude | float | 经度 |
latitude | float | 纬度 |
返回结构
json
{
"alerts": [
{
"alert_type": 156110203, // 预警类型,参考 AlertType
"area_code": "110102", // 区域编码
"color": {
"blue": 255,
"green": 100,
"red": 55
},
"data": [
{
"language_code": "zh-CN", // 语言编码
"name": "暴雨蓝色预警", // 预警名称
"text": "西城区气象台29日15时30分发布暴雨蓝色预警,预计29日夜间至30日夜间,西城区将出现小时降雨量超过30毫米的强降水,低洼地区可能出现积水,请注意防范。(数据来源:国家预警信息发布中心)", // 预警内容
"title": "西城区气象台发布暴雨蓝色预警[IV/一般]" // 预警标题
}
],
"id": "ALERT_CN_11010241600000_20240729153126", // 业务分配的唯一标识
"publish_time": 1722238200, // 预警发布时间戳(秒)
"region_code": "CN", // ISO 3166-1 Alpha-2 code
"source": 1 // 预警来源机构,参考 AlertSource
}
]
}
Alerts
Field | Type | Description |
---|---|---|
alerts | AlertRecord | 预警记录 |
AlertRecord
Field | Type | Description |
---|---|---|
alert_type | AlertType | 预警类型 |
area_code | string | 区域编码,可能是行政区划编码,也可能相关机构分配的区域编码 |
color | RGB Object | 颜色,根据各国气象局的标准定义的颜色;RGBA 中如果值为 0 则不返回 |
data | AlertData | 预警信息 |
id | string | 业务分配的唯一标识,不要直接解析 id 作为业务逻辑 |
publish_time | int64 | 预警发布时间戳(秒) |
region_code | string | ISO 3166-1 Alpha-2 code |
source | AlertSource | 预警来源机构 |
status | int32 | 预警状态:1 表示预警发布,2 表示预警继续,3 表示预警取消,4 表示预警过期;其中 3&4 只在预警 Webhook 推送中提供 |
AlertData
Field | Type | Description |
---|---|---|
language_code | string | 语言编码 |
level | string | 预警级别, 本地化的描述 |
name | string | 预警名称 |
text | string | 预警内容 |
title | string | 预警标题 |
AlertSource
随时可能新增枚举值,代码请做好兼容处理。
Number | Description |
---|---|
1 | 中国气象局 |
2 | 日本气象厅 |
AlertType
随时可能新增枚举值,代码请做好兼容处理。
枚举值以 ISO 3166-1 numeric-3 code 开头,后面跟随具体的预警类型。 比如如下表格里,中国的前缀为 156
,日本的前缀为 392
。
Number | Description |
---|---|
156100000 | 突发事件 |
156110000 | 自然灾害 |
156110100 | 水旱灾害 |
156110101 | 洪水 |
156110108 | 枯水 |
156110109 | 中小河流洪水和山洪气象风险 |
156110151 | 山洪灾害事件 |
156110152 | 农业干旱 |
156110154 | 生态干旱 |
156110200 | 气象灾害 |
156110201 | 台风事件 |
156110202 | 龙卷风事件 |
156110203 | 暴雨事件 |
156110204 | 暴雪事件 |
156110205 | 寒潮事件 |
156110206 | 大风事件 |
156110207 | 沙尘暴事件 |
156110208 | 低温冻害事件 |
156110209 | 高温事件 |
156110210 | 热浪事件 |
156110211 | 干热风 |
156110212 | 下击暴流事件 |
156110213 | 雪崩事件 |
156110214 | 雷电事件 |
156110215 | 冰雹事件 |
156110216 | 霜冻事件 |
156110217 | 大雾事件 |
156110218 | 低空风切变事件 |
156110219 | 霾 |
156110220 | 雷雨大风 |
156110221 | 道路结冰 |
156110222 | 干旱 |
156110223 | 海上大风 |
156110224 | 高温中暑 |
156110225 | 森林火险 |
156110226 | 草原火险 |
156110227 | 冰冻 |
156110229 | 重污染 |
156110230 | 低温雨雪冰冻 |
156110231 | 强对流 |
156110232 | 臭氧 |
156110233 | 大雪 |
156110234 | 寒冷 |
156110235 | 连阴雨 |
156110236 | 渍涝风险 |
156110237 | 地质灾害 |
156110238 | 强降雨 |
156110239 | 强降温 |
156110240 | 雪灾 |
156110241 | 森林(草原)火险 |
156110243 | 雷暴 |
156110247 | 春季沙尘天气趋势预警 |
156110248 | 降温 |
156110249 | 台风暴雨 |
156110250 | 严寒 |
156110251 | 沙尘 |
156110252 | 海上雷雨大风预警信号 |
156110254 | 海上雷电预警信号 |
156110255 | 海上台风预警信号 |
156110256 | 低温 |
156110257 | 道路冰雪 |
156110258 | 雷暴大风 |
156110262 | 海区大风 |
156110265 | 海区大雾 |
156110286 | 低温凝冻 |
156110287 | 低温冷害 |
156110291 | 低温冰冻 |
39200010 | 大雨 |
39200020 | 大雪 |
39200030 | 風雪 |
39200040 | 雷 |
39200050 | 強風 |
39200060 | 波浪 |
39200070 | 融雪 |
39200080 | 洪水 |
39200090 | 高潮 |
39200100 | 濃霧 |
39200110 | 乾燥 |
39200120 | なだれ(雪崩) |
39200130 | 低温 |
39200140 | 霜 |
39200150 | 着氷 |
39200160 | 着雪 |
39200170 | 暴風雪 |
39200180 | 暴風 |
预警颜色说明
《GB/T 37230—2018》定义了中国预警颜色规范,其中颜色等级对照如下:
等级 | 颜色 | RGB 值 |
---|---|---|
广东特有预警级别 | 白色 | 255/255/255 |
IV 级(一般) | 蓝色 | 55/100/255 |
III 级(较重) | 黄色 | 250/230/0 |
II 级(严重) | 橙色 | 240/150/20 |
I 级(特别严重) | 红色 | 220/40/40 |
批量获取 API
本接口重点为需要在地图叠加全国预警分布的客户提供一个方便的批量获取 API。 直接返回 GeoJSON 格式的数据,方便直接和地图交互。
调用方式:
bash
curl "https://singer.caiyunhub.com/v3/alert/all?token=token®ion_code=CN" \
-H 'If-None-Match: 123hfjkds678' \
-H 'Accept-Encoding: gzip, zlib, deflate, zstd, br'
正常情况下,接口在 Response Header 中会含有一个 x-cy-etag
值,在下一次调用时将 Etag 值赋给请求 Header 中的 If-None-Match
, 如果返回 HTTP 304 则表示数据没有变化,可以直接使用上一次的数据。
返回结构
json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [118.702032, 41.018482] },
"id": "ALERT_CN_13088141600000_20240806111120",
"properties": {
"alert_type": 156110214,
"area_code": "130881",
"color": { "red": 250, "green": 230 },
"data": [
{
"language_code": "zh-CN",
"title": "平泉市气象台发布雷电黄色预警[Ⅲ级/较重]",
"text": "平泉市气象台2024年08月06日11时10分发布雷电黄色预警信号:预计未来6小时内,我市全部乡镇将受雷电天气影响,雷雨时可能伴有雷暴大风、短时强降水和冰雹等强对流天气,请注意防范。(数据来源:国家预警信息发布中心)",
"name": "雷电黄色预警"
}
],
"id": "ALERT_CN_13088141600000_20240806111120",
"publish_time": 1722913880,
"region_code": "CN",
"source": 1,
"status": 1
}
},
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [125.744654, 42.284594] },
"id": "ALERT_CN_22052441600000_20240806103348",
"properties": {
"alert_type": 156110214,
"area_code": "220524",
"color": { "red": 250, "green": 230 },
"data": [
{
"language_code": "zh-CN",
"title": "柳河县气象台 发布雷电黄色预警[III级/较重]",
"text": "预计未来6小时内,我县有分布不均的雷电天气,可能会造成雷电灾害,局部地方伴有短时强降水、雷暴大风或冰雹等强对流天气,县应急局与县气象局联合提醒相关部门和广大群众注意加强防范(数据来源:国家预警信息发布中心)",
"name": "雷电黄色预警"
}
],
"id": "ALERT_CN_22052441600000_20240806103348",
"publish_time": 1722911788,
"region_code": "CN",
"source": 1,
"status": 1
}
}
]
}
Webhook 推送
POST Body:
json
{
"sign": "xxxx", // 根据规则生成的签名
"nonce": "xxxx", // 随机字符串
"server_time": 1722238200,
"alert": {
"alert_type": 156110203,
"area_code": "110102",
"color": {
"blue": 255,
"green": 100,
"red": 55
},
"data": [
{
"language_code": "zh-CN",
"name": "暴雨蓝色预警",
"text": "西城区气象台29日15时30分发布暴雨蓝色预警,预计29日夜间至30日夜间,西城区将出现小时降雨量超过30毫米的强降水,低洼地区可能出现积水,请注意防范。(数据来源:国家预警信息发布中心)",
"title": "西城区气象台发布暴雨蓝色预警[IV/一般]"
}
],
"id": "ALERT_CN_11010241600000_20240729153126",
"publish_time": 1722238200,
"expire_time": 1722238200, // 预警过期时间戳(秒)
"region_code": "CN",
"source": 1
}
}
签名计算规则
计算规则为:
sign = md5("{token}-{id}-{publish_time}-{nonce}-{server_time}")
Python/Go/Java/PHP 示例代码如下:
py
import hashlib
def generate_sign(token, id, publish_time, nonce, server_time):
# 拼接字符串
data = f"{token}-{id}-{publish_time}-{nonce}-{server_time}"
# 计算 MD5 签名
sign = hashlib.md5(data.encode()).hexdigest()
return sign
# 示例数据
token = "your_token"
id = "your_id"
publish_time = 1234567890
nonce = "your_nonce"
server_time = 9876543210
# 生成签名
sign = generate_sign(token, id, publish_time, nonce, server_time)
print(sign)
# Output: ed72493981fff6ddc4770dc70aeeb1ad
go
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
)
func generateSign(token, id string, publishTime int64, nonce string, serverTime int64) string {
// 拼接字符串
data := fmt.Sprintf("%s-%s-%d-%s-%d", token, id, publishTime, nonce, serverTime)
// 计算 MD5 签名
hash := md5.Sum([]byte(data))
return hex.EncodeToString(hash[:])
}
func main() {
// 示例数据
token := "your_token"
id := "your_id"
publishTime := int64(1234567890)
nonce := "your_nonce"
serverTime := int64(9876543210)
// 生成签名
sign := generateSign(token, id, publishTime, nonce, serverTime)
fmt.Println(sign)
// Output: ed72493981fff6ddc4770dc70aeeb1ad
}
java
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SignDemo {
public static void main(String[] args) {
String token = "your_token";
String id = "your_id";
long publishTime = 1234567890L;
String nonce = "your_nonce";
long serverTime = 9876543210L;
// 拼接字符串
String input = String.format("%s-%s-%d-%s-%d", token, id, publishTime, nonce, serverTime);
// 计算 MD5 签名
String sign = md5(input);
// 输出签名
System.out.println("计算出的签名: " + sign);
// 验证是否与预期结果匹配
String expectedSign = "ed72493981fff6ddc4770dc70aeeb1ad";
if (sign.equals(expectedSign)) {
System.out.println("签名匹配!");
} else {
System.out.println("签名不匹配!");
}
}
// 计算 MD5 哈希
public static String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hashBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
php
<?php
function calculateSign($token, $id, $publishTime, $nonce, $serverTime) {
// 拼接字符串
$input = sprintf("%s-%s-%d-%s-%d", $token, $id, $publishTime, $nonce, $serverTime);
// 计算 MD5 签名
return md5($input);
}
// 样例数据
$token = "your_token";
$id = "your_id";
$publishTime = 1234567890;
$nonce = "your_nonce";
$serverTime = 9876543210;
// 计算签名
$sign = calculateSign($token, $id, $publishTime, $nonce, $serverTime);
echo "计算出的签名: " . $sign . "\n";
// 预期的签名
$expectedSign = "ed72493981fff6ddc4770dc70aeeb1ad";
// 验证签名是否匹配
if ($sign === $expectedSign) {
echo "签名匹配!\n";
} else {
echo "签名不匹配!\n";
}
?>
更多语言签名计算代码
上述代码都是用 LLM 生成的,使用的 prompts 如下:
md
我有一个签名的计算方式为:
sign = md5("{token}-{id}-{publish_time}-{nonce}-{server_time}")
其中:
- token: str, eg "your_token"
- id: str, eg "your_id"
- publish_time: int64, eg 1234567890
- nonce: str, eg "your_nonce"
- server_time: int64, eg 9876543210
帮我编写对应的 Python&Go 的 demo,并用样例数据验证签名计算是否为 `ed72493981fff6ddc4770dc70aeeb1ad`。
请根据自己的需求修改 prompts,并用样例数据验证签名计算是否正确。