本文算是此系列的第一篇,我打算写写济南公交的服务端 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
返回
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. 车辆搜索界面
搜索界面的车辆相似查询
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. 路线详情界面
GET –> http://60.216.101.229/server-ue2/rest/buslines/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 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. 公告界面
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 的实现。