改造CIMISS MUSIC接口的Python SDK

目录

背景

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版本。

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

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

下面介绍经过重新设计的SDK库 —— nuwe-cimiss-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的架构如下所示:

accountaccountserver configserver configinterface idinterface idinterface paramsinterface paramsCimissClientCimissClientgenerate urlgenerate urlrequestrequestparse responseparse responselocal operationlocal operation

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

使用

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

使用 nuwe_cimiss.CimissClient 类从 CIMISS 中检索数据。

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

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

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

from nuwe_cimiss import CimissClient

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 = CimissClient(
    user=user,
    password=password,
    config_file=client_config_path
)
result = client.callAPI_to_array2D(interface_id, params)

参考

perillaroc/nuwe-cimiss-python

perillaroc/nuwe-cimiss-cpp