改造CIMISS MUSIC接口的Python SDK

目录

本文仅代表笔者对 2019 年 10 月时 MUSIC 接口发布版本的观点,随着版本更新及对接口进一步研究,笔者后续观点已有变化。

注:CMADaaS 已提供官方 Python 3 的 MUSIC 接口。

2021.04.15

背景

CIMISS 是全国综合气象信息共享平台 (China Integrated Meteorological Information Service System) 的简称。 由国家气象信息中心牵头建设,用于共享气象业务的数据信息。 对于数值预报中心来说,CIMISS 一般用于检索观测资料。

MUSIC 接口是气象数据统一服务接口 (MUSIC:Meteorological Unified Service Interface Community) 的简称,是为访问 CIMISS 库中保存的数据而开发的接口。 该接口提供统一、标准、丰富的数据访问服务和应用编程接口 (API),为应用系统提供唯一权威的数据接入服务。

今年 6 月 30 日开放测试的 气象大数据云平台 看起来像是对 CIMISS 系统的升级,不仅包含数据,提供包括内置算法在内的计算功能。 该平台提供了 MUSIC 2.0 版的接口。

MUSIC接口的版本

当前业务系统正在使用的 MUSIC 接口版本是1.6,从 MUSIC接口内网网址 下载。

2.0 版本与 1.6 版本最大的区别在于使用不同的库实现数据序列化。 1.6 版本使用 ICE,2.0 版本使用 Protobuf

MUSIC 1.6 版本只提供了 Python 2.6 的 SDK,而没有提供更广泛使用的 Python 2.7 版本。所以我没有使用过这个版本的 SDK。

MUSIC 2.0 版本提供了 Python 2.7 的 SDK,却没有提供 Python 3.x 版本。 Python 2.7 版本将于 2020 年停止维护,所以我觉得现在发布的 Python 库都支持 Python 3.x 版本。

注:CMADaaS 已提供官方 Python 3 的 MUSIC 接口。[2021.04.15]

不过好在 Protobuf 生成的 Python 代码同时支持 Python 2 和 3,我花了一些时间将整个 MUSIC Python SDK 移植到 Python 3。

修改代码过程中,发现 MUSIC Python SDK 库的代码不像是熟悉 Python 的程序员编写的,编码方式有一些 C/C++ 的风格。 从而萌生了重新写一个 MUSIC Python SDK 的想法。

下面介绍经过重新设计的 SDK 库 —— nuwe-cmadaas-python

起步

重写的第一步就是编写 protobuf 的定义文件。 Python 这类脚本语言的优势在于不容易隐藏源码,可以从 Python SDK 中的 apiinterface_pb2.py 文件反推回 protobuf 定义文件。

MUSIC 的 protobuf 仅使用基础功能,所以很容易就能得到 proto 文件。

syntax = "proto3";

package cma.music.pb;

message RequestInfo{
    int32 errorCode = 1;
    string errorMessage =2;
    string requestElems = 3;
    string requestParams = 4;
    string requestTime = 5;
    string responseTime = 6;
    int32 rowCount = 7;
    int32 takeTime = 8;
    int32 colCount = 9;
}

message RetArray2D{
    repeated string data = 1;
    RequestInfo request = 2;
    repeated string elementNames = 3;
}

message RetGridArray2D{
    repeated float data = 1;
    RequestInfo request = 2;
    float startLat = 3;
    float startLon = 4;
    float endLat = 5;
    float endLon = 6;
    int32 latCount = 7;
    int32 lonCount = 8;
    float lonStep = 9;
    float latStep = 10;
    repeated float lats = 11;
    repeated float lons = 12;
    string units = 13;
    string userEleName = 14;
}

message FileInfo{
    string fileName = 1;
    string savePath = 2;
    string suffix = 3;
    string size = 4;
    string fileUrl = 5;
    string imgBase64 = 6;
    repeated string attributes = 7;
}

message RetFilesInfo{
    repeated FileInfo fileInfos = 1;
    RequestInfo request = 2;
}

message StoreArray2D{
    repeated string data = 1;
    int32 row = 2;
    int32 col = 3;
    int32 fileflag = 4;
    repeated string filenames = 5;
    int32 is_backstage = 6;
    string client_mount_path = 7;
    string server_mount_path = 8;
}

message RetDataBlock{
    string dataName = 1;
    bytes byteArray = 2;
    RequestInfo request = 3;
}

message RetGridVector2D{
    repeated float u_datas = 1;
    repeated float v_data2 = 2;
    RequestInfo request = 3;
    float startLat = 4;
    float startLon = 5;
    float endLat = 6;
    float endLon = 7;
    int32 latCount = 8;
    int32 lonCount = 9;
    float lonStep = 10;
    float latStep = 11;
    repeated float lats = 12;
    repeated float lons = 13;
    string u_EleName = 14;
    string v_EleName = 15;
}

message RetGridScalar2D{
    repeated float datas = 1;
    RequestInfo request = 2;
    float startLat = 3;
    float startLon = 4;
    float endLat = 5;
    float endLon = 6;
    int32 latCount = 7;
    int32 lonCount = 8;
    float lonStep = 9;
    float latStep = 10;
    repeated float lats = 11;
    repeated float lons = 12;
    string units = 13;
    string userEleName = 14;
}

message StoreGridData{
    repeated string attributes = 1;
    int32 pointflag = 2;
    repeated float Lats = 3;
    repeated float Lons = 4;
    repeated float datas = 5;
}

message StoreBlockData{
    repeated string attributes = 1;
    bytes data = 2;
}

使用新的 proto 文件编译 python 代码,会发现与之前的代码有所不同。 不过经测试发现,不影响对消息的解析,可以正常使用。

架构

CIMISS MUSIC 接口调用包括下面几个步骤:

  • 根据用户提供的参数和接口生成相应的URL
  • 访问 URL 获取响应
  • 对响应进行解析,包括错误处理和 protobuf 反序列化
  • 对响应进行本地操作,可选步骤

整个 API 的架构如下所示:

不过我这里要指出的是,MUSIC 接口在 URL 中使用明文传输密码,即使在内网也充满风险。 不过这不是我能接触到范畴,所以还是当做没看见比较好。

注:2020 年新版 MUSIC 接口已不再使用明文密码传输。 2021.04.15

使用

MUSIC 接口仅适用于气象局内网用户,使用前请先申请账户。

使用 nuwe_cmadaas.CMADaaSClient 类从 CMADaaS 中检索数据。

需要提供 CMADaaS 服务的相关参数,可以保存在当前目录 client.conf 文件中, 或者在创建 nuwe_cmadaas.CMADaaSClient 对象显式指定。 参数包括:

  • music_server: MUSIC 接口 ip 地址,必须指定
  • music_port:MUSIC 接口端口号,必须指定
  • music_connTimeout:连接超时,秒,可选
  • music_readTimeout:数据读取超时,秒,可选
  • music_ServiceId:默认服务节点 id

下面的示例展示如何检索地面观测资料。

from nuwe_cmadaas import CMADaaSClient

client_config_path="path/to/client/config/file"
user="user name"
password="user password"
server_id = "server id"

interface_id = "getSurfEleByTimeRange"

params = {
    "dataCode": "SURF_CHN_MUL_HOR",
    "elements": "Station_Id_d,Lat,Lon,Alti,Day,Hour,PRS_Sea,TEM,"
    "DPT,WIN_D_INST,WIN_S_INST,PRE_1h,PRE_6h,PRE_24h,PRS",
    "timeRange": "[20190817000000,20190817020000)",
    "orderby": "Station_ID_d:ASC",
    "limitCnt": "10",
}

client = CMADaaSClient(
    user=user,
    password=password,
    config_file=client_config_path
)
result = client.callAPI_to_array2D(interface_id, params)

参考

perillaroc/nuwe-cmadaas-python

perillaroc/nuwe-cimiss-cpp

相关博文:

一种封装CMADaaS MUSIC Python接口的方法