一、协议规范
1.1 请求
- 当请求中没有二进制数据时。
json格式数据 - 当请求中含有二进制数据时。
4+json格式数据+二进制数据+20字节的二进制数据SHA1 - 每个请求中都有version、nonce字段
字段 类型 version string app正使用的Rose版本。示例:1.0.9-20210516。server内部有一个能支持的最低Rose版本。一旦app的Rose版本低于那个版本,应答返回-2(app版本太低,server不支持)。如果version不是x.x.x-xxxxxxxx(x全是数字)格式, 报ParamError。 nonce int 一个整型随机数。server的应答也须有这同名、同值字段。以便app通过它们判断这是一对请求、应答
1.2 应答
字段 | 类型 | |
code | int | 成功、失败时都必须包含。值0表示成功,负数表示失败。不能出现正数。 |
msg | string | 成功、失败时都必须包含。用英文描述的处理结果。 |
nonce | int | 成功、失败时都必须包含。值等于client请求中的nonce(一个整型随机数)。 |
results | object | 在成功时必须包含,失败时则禁止出现。服务端中的被调用方法决定了该成员的值。 |
失败示例
{"code":-7,"msg":"password error", "nonce": 13778}
1.3 code值
enum | code | |
Success | 0 | 成功 |
ParamError | -1 | 参数值错误 |
ClientVersionTooLow | -2 | app版本太低,server不支持 |
InvalidDeiveSession | -5 | http sessionid错误 |
UserNotExisted | -6 | 用户不存在 |
PasswordError | -7 | 密码错误 |
SignError | -10 | SHA1签名不匹配 |
FileNotExisted | -11 | 文件不存在 |
RequestNotSupported | -15 | server不支持该命令 |
AuthorizationError | -16 | 该用户存在,但没有授权访问 |
如果错误情形不在上面的,可自加一个负数的code值。
二、命令
2.1 下载小程序
- 请求URL。
http://ip:port/cswamp/device/getapplet - 请求方式。
POST - 不需要已登录
请求
参数 | 必选 | 类型 | 说明 |
version | yes | string | 见“1.1 请求” |
nonce | yes | int | 见“1.1 请求” |
type | yes | string | distribution/development。distribution:Applet Store中的小程序。development:个人中心/小程序中的小程序,如果Applet Store中已经是最新的,返回错误FileNotExisted(-11)。 |
bundleid | yes | string | 该小程序绑定的Bundle ID。 示例:aplt.leagor.blesmart |
应答
字节数 | ||
json长度 | 4 | 后面json数据字节数(大端序) |
json数据 | 见底下json数据 | |
二进制数据块 | rsp的文件长度 | *.rsp文件 |
SHA1签名 | 20 | 二进制数据块的SHA1签名 |
json数据(results)
参数 | 必选 | 类型 | 说明 |
name | yes | string | 小程序名称 |
title | yes | string | 小程序名称(留它是为和以前版本兼容,过段时间再删) |
subtitle | yes | string | 小程序副标题 |
time | yes | timestamp | 秒。distribution:小程序在商店开售时间。development:小程序上传时间 |
username | yes | string | 小程序开发者 |
rspfsize | yes | int | 二进制数据中*.rsp字节数 |
app | yes | string | 该小程序能运行在的app。语义等同findapplet应答中的app字段。 |
2.2 搜索小程序
- 请求URL。
http://ip:port/cswamp/device/findapplet - 请求方式。
POST - 需要/不需要已登录
只在Applet Store中搜索。
请求
参数 | 必选 | 类型 | 说明 |
version | yes | string | 见“1.1 请求” |
nonce | yes | int | 见“1.1 请求” |
sessionid | no | string | login时返回的sessionid |
app | no | string | 值:launcher或kdesktop。1)sessionid不空时,要得该人名下和该app关联的、该人的名下小程序。2)sessionid空时,app可以是空,如果不空,搜索条件上小程序还需能在该app运行,并且client最多只会传一个,即不是launcher就是kdesktop。 |
maxapplets | no | int | 指示只返回最前面的maxapplets个小程序。maxapplets不在[1, 30]范围时,强制认为30。 |
bundleids | no | string | 小程序Bundle ID,多个时用逗号分隔。 |
name | no | string | 小程序名称。一旦不为空,名称中需含有name字符串。 |
依sessionid是否为空,分两情况。
- sessionid不空时,sessionid必须是一个正有效的sessionid,此时app不能为空,忽略maxapplets、bundleids、name。目的是得到该用户名下、该类app的小程序。什么是该用户名下、某类app的小程序,见“2.5 同步小程序列表”。
- sessionid为空时,此时须检查app、maxapplets、bundleids、name。bundleds、name是两个条件,当中至少有一个不能为空,当两个都不空时,总条件是逻辑与。bundleids不为空时,返回那些小程序。如果此时name也不为空,这些小程序名称都需要含有name字符串。如果app同时不为空,查到的小程序还需要能在这app运行。(旧版本:sessionid为空时,此时须检查maxapplets、bundleids、name,忽略app。bundleds、name是两个条件,当中至少有一个不能为空,当两个都不空时,总条件是逻辑与。bundleids不为空时,返回那些小程序。如果此时name也不为空,这些小程序名称都需要含有name字符串。)
应答(json数据(results))
count:实际搜索到满足条件的小程序数目。
{ "code": 0, "msg": "success", "nonce": 13778, "results": { "count": 34 "applets": [{ "bundleid": "aplt.leagor.blesmart", "name": "BLE Smart", "subtitle": "BLE测试工具", "time": 1622509363, "username": "兰栖科技", "rspfsize": 15949608, "version": "1.0.2-20210131" …… }] } }
参数 | 必选 | 类型 | 说明 |
bundleid | yes | string | 小程序bundleid |
name | yes | string | 小程序名称 |
subtitle | yes | string | 小程序副标题 |
time | yes | timestamp | 秒。distribution:小程序在商店开售时间。 |
username | yes | string | 小程序开发者 |
rspfsize | yes | int | 该小程序*.rsp的文件字节数 |
version | yes | string | 该小程序版本。示例:1.0.9-20210516 |
roseversion | yes | string | 该小程序基于的Rose版本。示例:1.0.8 |
app | yes | string | 该小程序能运行在的app,多个时逗号隔开。示例:launcher,kdesktop |
2.3 上传文件
- 请求URL
http://ip:port/cswamp/device/uploadfile - 请求方式
POST - 需要登录/不需要已登录
请求
字节数 | ||
json长度 | 4 | 后面json数据字节数(大端序) |
json数据 | 见底下json数据 | |
二进制数据块 | json块中size值 | 文件内容 |
SHA1签名 | 20 | 二进制数据块的SHA1签名 |
json数据
参数 | 必选 | 类型 | 说明 |
version | yes | string | 见“1.1 请求” |
nonce | yes | int | 见“1.1 请求”。注1。 |
sessionid | opt | string | 须要登录后才能上传的文件时,必须提供。login时返回的sessionid |
file | yes | string | 文件。注2 |
offset | yes | int | 此次要传输的开始偏移。注3 |
size | yes | int | 此次要上传的字节数 |
end | yes | bool | true:后面已没有文件数据,可关闭。false:后面还会有该文件数据。注4 |
注1。除公用功能之外,此命令中的nonce还一个作用:传输同一个文件时,会用同一个noce值。如果nonce不同,即使是offset都接上了,那也不能认为是一个文件。
注2。file指示要传什么文件。文件可能是哪平台下哪app的升级包。后面还会有用户地图、定时任务、小程序等。
file | sessionid | 功能说明 | 文件说明 |
launcher.android | 不须要 | android平台launcher升级包 | *.rsp。Tag3-L4=2,android apk |
kdesktop.android | 不须要 | android平台kdesktop升级包 | *.rsp。Tag3-L4=2,android apk |
注3。offset值是0时,先把同名文件清空,打开,写入数据。非0时,要同时满足三个条件才算正确:同名文件需存在、nonce和之前一样、已有长度是offset,一旦有一个不满足,不必等待,返回一个用response_code指示错误的应答。
注4。server一旦处理完一个end=false请求,溢出时间设为30秒,如果30秒后没有收到下一个uploadfile,认为上传此次上传文件失败。
应答(results)
参数 | 必选 | 类型 | 说明 |
2.4 下载文件
- 请求URL
http://ip:port/cswamp/device/downloadfile - 请求方式
POST
请求
参数 | 必选 | 类型 | 说明 |
version | yes | string | 见“1.1 请求” |
nonce | yes | int | 见“1.1 请求” |
sessionid | opt | string | 须要登录后才能上传的文件时,必须提供。login时返回的sessionid |
file | yes | string | 文件。见“2.3 上传文件”中的file |
offset | yes | int | 此次要传输的开始偏移。 |
size | yes | int | 此次要传输的字节数 |
应答
字节数 | ||
json长度 | 4 | 后面json数据字节数(大端序) |
json数据 | 见底下json数据 | |
二进制数据块 | <=req.size | 当文件中字节小于请求中的size时,只返回实际剩余字节 |
SHA1签名 | 20 | 二进制数据块的SHA1签名 |
json数据(results object)
参数 | 必选 | 类型 | 说明 |
fsize | yes | int | 此文件长度。不是请求中的size |
req.offset == fsize时,不必传“二进制数据块”和SHA1签名,但json数据还是按成功时填充。
如果server没法传输数据,像该文件不存在,参数req.offset超过文件长度等,不必传“二进制数据块”和SHA1签名,json部分指示错误。
2.5 登录
- 请求URL
http://ip:port/cswamp/device/login - 请求方式
POST - 需要/不需要已登录
设备登录。
请求
参数 | 必选 | 类型 | 说明 |
version | yes | string | 见“1.1 请求” |
nonce | yes | int | 见“1.1 请求” |
type | yes | string | password/cookie |
username | yes | string | 用户名 |
password | yes | string | password:密码。cookie:上次login时返回的pwcookie |
deviceid | yes | string | 设备唯一标识。值是32个字符的uuid。可以这么认为,只要是同一台设备,这个值总是一样的。 |
devicename | yes | string | 登录时设备易记名。示例:iOS(kDesktop)、Android设备。cswamp不解析,原样存储。 |
登录示例。用户名:test,密码:123456。
- [机器人]test在机器人(launcher)手工输入密码的方式登录。发向cswamp的login请求中,deviceid:a11ee49e9fe14e72a295e94d3263af73,devicename:launcher(Android),type:password。
- [cswamp]收到这个请求,判断password是否正确。一旦正确,生成两个uuid,一个是sessionid,一个是pwcookie。同时生成一条以a11ee49e9fe14e72a295e94d3263af73(deviceid)为key的登录记录。
- [机器人]收到应答,把pwcookie存储在本地配置文件preferences,它将作为后绪cookie方式时的登录密码。
- [机器人]发生重启。
- [机器人]自动登录。发向cswamp的login请求中,deviceid:a11ee49e9fe14e72a295e94d3263af73,devicename:launcher(Android),type:cookie,password:填preferences文件中的pwcookie,即上次login收到的pwcookie。
- [cswamp]收到这个请求,以a11ee49e9fe14e72a295e94d3263af73(deviceid)为key在登录记录表中搜索,发现表中有以收到的pwcookie为key的记录,认为正确,可以登录。并生成两个uuid,一个是sessionid,一是个pwcookie。同时修改这条以a11ee49e9fe14e72a295e94d3263af73(deviceid)为key的登录记录,像pwcookie、最后登录时间。
- [iPhone]test在控制端手机(kdesktop)手工输入密码的方式登录。发向cswamp的login请求中,deviceid:3cc51905c1a64d8a89fb981f6ea35d86,devicename:kdesktop(iOS),type:password。
- [cswamp]收到这个请求,判断password是否正确,并生成两个uuid,一个是sessionid,一是个pwcookie。同时生成一条以3cc51905c1a64d8a89fb981f6ea35d86(deviceid)为key的登录记录。——至此,test这个用户已有两条登录记录,而且这两条是同时有效,即这两个sessionid要同时有效。
登录这么复杂,主要是两个原因。
- 为安全,设备端禁止存储密码到文件。为解决这问题,自动登录改用pwcookie。由于pwcookie和密码没任何关系,即使别人拿到它也猜不出密码。为更安全,每次login后,pwcookie都要变一次。这样pwcookie真泄露了,本人很快能通过login操作让泄露的pwcookie失效。
- 同一个用户名会同时在多个设备上正登录着。而且同时登录,会是个普遍现象。
cswamp在“个人中心”——“App”页,提供显示、清除登录记录功能。需要这功能,有三个原因。
- 设备和deviceid之间不是真的唯一。deviceid即使和某一硬件绑定,像网卡MAC地址,也会发生维修换了网卡。Rose生成devcieid没关联硬件,是判断配置文件pereferences是否存在。不存在时,用操作系统api生成一个uuid。由于只要不卸载app,pereferences就会一直存在,deviceid也就一直不变了。但是,万一app卸载又重装,这设备就会生成新uuid,针对这设备,cswamp的登录记录表就有了两个deviceid。
- deviceid+pwcookie可能泄露。泄露会造成何样影响分两种情况。第一种,原用户test继续用该deviceid。这时test的login操作会自动使泄露的deviceid+pwcookie无效,相对来说恶果要小些。第二种,test不再用该deviceid。这时泄露的deviceid+pwcookie将一直有效。别人就可用它持续获得test私有信息,甚至篡改数据。
- 用户一旦发现数据有异常,通过查看登录记录,可判断是否有人入侵过,并自行清除。一旦清除所有登录记录,意味着设备都要进行一次密码登录。
在“App”页,同时可查看本用户名下的launcher、kdesktop类的小程序列表。
应答(json数据(results))
参数 | 必选 | 类型 | 说明 |
sessionid | yes | string | cswample生成的、唯一指示此次登录的sessionid |
pwcookie | yes | string | app后绪以cookie方式登录时,填写的password |
2.6 退出登录
- 请求URL
http://ip:port/cswamp/device/logout - 请求方式
POST - 需要已登录
退出登录。cswamp在登录记录表中删除此次deviceid为key的记录。
请求
参数 | 必选 | 类型 | 说明 |
version | yes | string | 见“1.1 请求” |
nonce | yes | int | 见“1.1 请求” |
sessionid | yes | string |
应答(json数据(results))
参数 | 必选 | 类型 | 说明 |
2.7 同步小程序列表
- 请求URL
http://ip:port/cswamp/device/syncappletlist - 请求方式
POST - 需要已登录
向server上的小程序列表添加、删除小程序。对每种app,server需各维护一个列表。目前两种app,字符串标识分别是launcher、kdesktop,应而需维护两个小程序列表。
为什么每种app各需一个?假设aplt.leagor.pan是个机器人底盘驱动小程序,launcher(机器人)会安装,(kdesktop)iphone控制端则不会,安装了也用不了。而这两个设备可能登录的是同一个用户名test。于是test在机器人登录时,那它下的launcher列表将包含aplt.leagor.pan这个小程序;iphone上登录时,下的kdesktop列表则不包含它。
请求
参数 | 必选 | 类型 | 说明 |
version | yes | string | 见“1.1 请求” |
nonce | yes | int | 见“1.1 请求” |
sessionid | yes | string | |
app | yes | string | launcher或kdesktop |
add | no | string | 要添加的小程序bundleid。是多个时,中间用逗号隔开 |
remove | no | string | 要移除的小程序bundleid。是多个时,中间用逗号隔开 |
add、remove可能都为空,此时client只是想快速得到该人、该app下小程序的bundleid列表。
应答(json数据(results))
参数 | 必选 | 类型 | 说明 |
applet | yes | string | 经过此次操作后,该人、该app下、且正存在于商店的小程序bundleid,bundleid之间用逗号隔开。client可能add了错误bundleid、该bundleid可能已下架,要剔除 |