泉城公交开发手记(二) API分析

本文算是此系列的第一篇,笔者打算写写济南公交的服务端 API。当下的环境,基本每个应用都会具备联网请求数据的功能,公交客户端这种实时性很强的应用更是如此。既然我们打算做一个第三方客户端,那么第一步就是先要拿到各个车辆的实时数据。下面笔者会通过抓包来分析原版 369 出行的各个请求,关于抓包过程之前笔者也写过一篇文章介绍,这里就不多赘述了。

因为请求众多,笔者这里只针对实际需要用到的数据进行说明,无用的类似请求广告图片什么的就不写了。

首次打开提示需要登录用户名,这部分其实是无用的。正常的流程会在用户登录时服务端返回一个 Token,后续请求会携带这个 Token。然而 369 出行的这个登录流程完全是无用的,登录的成功与否只是决定能不能进入下一个页面。还有一个值得吐槽的是整个登录流程用户名密码明文传输…

0. 参数说明

向微步服务器的所有请求都需要在 Header 中加上 version 参数,值是版本号,示例
version = android-insigma.waybook.jinan-2337,后面不再说明。

Json 返回的变量名,笔者也是只说明一次的,后面重复的也不会再说明。


1. 首页

GET –> http://www.iwaybook.com/server-ue2/rest/servers-v2/370100

数据 说明
370100 济南市身份证号六位数字地址码

返回

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"status": {
"code": 0
},
"result": {
"id": 3,
"name": "370100",
"httpAddr": "60.216.101.229",
"functions": "{\"bus\":{\"httpAddr\":\"60.216.101.229\",\"transfertype\":\"1\"}}",
"state": 1,
"useToken": false
}
}

变量 说明
httpAddr 下一步请求的服务器地址

GET –> http://jinan.iwaybook.com/download/update.json

数据 说明
version 当前已安装的版本

返回

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"status": {
"code": 0,
"msg": ""
},
"result": {
"versionCode": 2337,
"versionName": "3.3.7",
"descriptions": ["1.增加了“车辆租赁”"],
"must": false,
"url": "http://60.216.101.229/download/jinan.apk"
}
}

变量 说明
versionCode 最新 versionCode
versionName 最新 versionName
descriptions 更新日志
must 如果为 true,会强制更新,不然无法进入。false 则不会
url 最新版本下载链接

2. 车辆搜索界面

搜索界面的车辆相似查询
device-2018-01-16-154733.png

GET –> http://60.216.101.229/server-ue2/rest/buslines/simple/370100/118/0/20

数据 说明
60.216.101.229 上文中请求获取到的 httpAddr,后续也是这个地址
118 路线编号
0 从第几个条目请求
20 请求多少个条目

返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"status": {
"code": 0,
"msg": ""
},
"result": {
"pageParam": {
"offset": 0,
"len": 20,
"totalNum": 2
},
"result": [{
"id": "223",
"lineName": "118",
"startStationName": "公交祝甸车场",
"endStationName": "市立五院",
"updateTime": "Sep 29, 2017 12:25:11 AM"
}, {
"id": "224",
"lineName": "118",
"startStationName": "市立五院",
"endStationName": "公交祝甸车场",
"updateTime": "Sep 29, 2017 12:25:31 AM"
}]
}
}

变量 说明
id 路线ID
lineName 路线编号
startStationName 始发站
endStationName 终点站
updateTime 信息更新时间

这里需要注意同一路车的去程与返程是两个不同的 ID


3. 路线详情界面

device-2018-01-16-172339.png

GET –> http://60.216.101.229/server-ue2/rest/buslines/370100/223

数据 说明
223 路线ID

返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
{
"status": {
"code": 0,
"msg": ""
},
"result": {
"id": "223",
"area": 370100,
"lineName": "118",
"startStationName": "公交祝甸车场",
"endStationName": "市立五院",
"stations": [
{
"id": "1",
"area": 370100,
"stationName": "公交祝甸车场",
"lng": 117.09900257524,
"lat": 36.703679321059,
"buslines": "",
"state": "0",
"updateTime": "Sep 29, 2017 12:25:11 AM",
"distance": 0,
"busLineList": []
},
{
"id": "2",
"area": 370100,
"stationName": "祝甸",
"lng": 117.09818542729,
"lat": 36.701505610837,
"buslines": "",
"state": "0",
"updateTime": "Sep 29, 2017 12:25:11 AM",
"distance": 0,
"busLineList": []
}
...
...
],
"ticketPrice": "票价一元",
"operationTime": "祝甸5:30-00:00 市立五院",
"owner": "",
"linePoints": "117.09900257524_36.703679321059,117.09818542729_36.701505610837,117.09402184523_36.701017213509,117.09066994065_36.700634744005...",
"updateTime": "Sep 29, 2017 12:25:11 AM",
"state": "0"
}
}

变量 说明
stations 是一个 List。该路线所有站点的信息
stationName 站点名
lng 经度坐标
lat 纬度坐标
state 站点状态。0 可用,1 不可用
ticketPrice 票价
linePoints 所有站点的坐标。以下划线_分隔经度和纬度

该路线的所有站点会在 stations 中体现,stations 的大小就是该路线所有站点的数量。
这里的 lng, lat 经纬度属于百度 BD09 坐标,后面会详细说明。
linePoints 是一些字符串,所有站点的坐标。实际没什么用处,因为上文的 stations 中已经包含各个站点的信息了。


GET –> http://60.216.101.229/server-ue2/rest/buses/busline/370100/223

返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
"status": {
"code": 0,
"msg": ""
},
"result": [{
"busId": "4635",
"lng": 116.973701,
"lat": 36.66398,
"velocity": 22.883572962605573,
"isArrvLft": "2",
"stationSeqNum": 23,
"status": "1",
"buslineId": "223",
"actTime": "Jan 16, 2018 03:50:04 PM",
"cardId": "4635",
"orgName": "",
"averageVelocity": 9.565269318966328,
"coordinate": 0
}, {
"busId": "4631",
"lng": 116.957313,
"lat": 36.654813,
"velocity": 50.211262538794415,
"isArrvLft": "2",
"stationSeqNum": 27,
"status": "1",
"buslineId": "223",
"actTime": "Jan 16, 2018 03:49:54 PM",
"cardId": "4631",
"orgName": "",
"averageVelocity": 9.178488660594233,
"coordinate": 0
}
...
...
]
}

变量 说明
busId 车辆自编号
stationSeqNum 即将到达第多少个站
actTime 最后活动时间
cardId 报站器ID
averageVelocity 平均时速

busId 是该车的自编号,由济南公交公司分配,方便管理
stationSeqNum 即将到达第几个站,参见上文的 stations
这里的 lng, lat 经纬度属于地球 WGS-84 坐标

可以看到这里使用的坐标系统和上文中的不同,笔者这里就简略介绍一下这几种坐标的区别。

WGS-84 坐标系,是国际标准坐标系。从专业 GPS 设备中取出的数据遵循这种坐标,也是国际地图提供商所使用的坐标系。

GCJ-02 坐标系,也叫国测局坐标系,又称火星坐标。是由中国国家测绘局指定的一种大地坐标系。会对原始坐标进行算法加密,加入随机偏移,隐藏真实位置。理论上不可逆推。国测局规定国内出版的各种地图系统(包括电子形式),必须至少采用 GCJ-02 对地理位置进行首次加密。

BD-09 坐标系,是百度公司的加密算法坐标系,同样是一种偏移算法。该算法不公开。据传是从 GCJ-02 加密而来,也不一定,也许直接从 WGS-84 转换而来也不得而知

这三种坐标系的互相转换,网上也有流传方法,但并不完美。


3. 公告界面

device-2018-01-16-181855.png

GET –> http://60.216.101.229/server-ue2/rest/busAnnouncements/370100/all/0/20

返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"status": {
"code": 0,
"msg": ""
},
"result": {
"pageParam": {
"offset": 0,
"len": 20,
"totalNum": 238
},
"result": [{
"id": "ab9f877a737f42688cd16d73065cd39f",
"area": 370100,
"title": "1月13日起,140路调整部分运行路段",
"content": "受蓝翔路道路施工影响,1月13日起,140路调整部分运行路段。\n\n140路调整后沿蓝翔中路向东、东宇大街向南、粟山路向东再向南、小清河北路向东恢复原线,新设时代总部基地西门、东宇花园、粟山路东宇大街、东沙王庄、粟山路黄岗路、王炉庄北、粟山路永鼎路站点,将王炉庄站点迁移至粟山路路口东侧,撤销蓝翔中路中段、蓝翔路蓝翔中路、时代总部基地、卢庄工业园、蓝翔路粟山路、北辛庄北、北辛庄站点。",
"publisher": "济南市公共交通总公司",
"updateTime": "Jan 11, 2018 03:51:21 PM",
"state": "1",
"valid": 1
}
...
...
]
}
}

变量 说明
totalNum 全部公告数量
title 标题
content 内容
publisher 发布人
updateTime 发布时间
valid 是否可用

有了这些必要的信息,已经可以开始做一个第三方的客户端了。下一篇文章,笔者将会详细介绍自定义线路图 View 的实现。