改造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的架构如下所示:

account
account
server config
server config
interface id
interface id
interface params
interface params
CimissClient
CimissClient
generate url
generate url
request
request
parse response
parse response
local operation
local 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