Appearance
2. 接入准备
2.1 服务地址与协议
| 项 | 值 | 说明 |
|---|---|---|
| 服务地址 | https://<控制台地址>:8095 | 端口固定 8095 |
| 协议 | 纯 HTTPS | 未配置 HTTP 端口,TLS 最低版本 TLS 1.3 |
| 路径前缀 | /api/mlinkClient | 所有接口均以该前缀开头 |
| 证书 | 自签(server.crt / server.key) | 需要跳过校验或导入仓库根的 ca.pem |
| 请求体上限 | 约 200MB | 同时约束文件上传,点表分片见 4.5 |
| 静态资源 | / 指向前端页面 | 与 API 同源 |
| CORS | 无 CORS 响应头 | 浏览器端必须走同源反代;脚本客户端不受限 |
自签证书的处理方式:命令行客户端用 -k / --insecure 跳过校验。
bash
curl -sk "https://<控制台地址>:8095/api/mlinkClient/version/get"【注意】生产集成建议把
ca.pem加入信任链,而不是长期跳过证书校验。
2.2 请求 / 响应公共约定
响应包装结构(统一包装生效时)为:
| 字段 | 类型 | 说明 |
|---|---|---|
code | int | 200=成功;-1=业务失败;51=参数校验失败(真机实测响应 {"code":51,"msg":"Validation Failed","data":"<哪个字段不合法>"},不只是"内部错误");54=Missing Parameter(必填参数缺失,实测于 upoint/import、driver/upload);68=Internal Panic(服务端 panic 被兜住,data 里是 panic 文本);大于 1 的其它值为具体错误码 |
msg | string | 提示信息。是 msg,不是 message |
data | object | 业务数据 |
json
{ "code": 200, "msg": "ok", "data": { } }但并非所有接口都走统一包装。 部分控制器自行写响应,此时响应体是各接口自己的结构;二次开发必须按接口逐个判成败:
| 响应形态 | 典型接口 | 判成败方式 |
|---|---|---|
统一包装 {code,msg,data} | 登录、连接列表、多数监控接口 | code == 200 |
裸结构,无外层 code | 建服务({"app":[...]})、建通道({code,msg,app,channelName}) | 看内层 err.code |
{"err":{"code":...,"msg":"..."}} | pkg/misc.ReturnErrCode 系列 | err.code == 200 |
| 纯文本 | das/state(running / stop)、das/check(true / false) | 直接比对文本 |
| 大写字段 | channel/info(Code / Msg / Pid / ...) | 注意字段大小写 |
HTTP 500 + PopupWindow | 通道增删改被 HTTP 驱动拦截 | 看 HTTP 状态码与 error 字段 |
| 文件流 | 测点导出、通道导出、日志下载 | Content-Type: application/octet-stream |
失败响应形态:
| 触发场景 | 响应 |
|---|---|
| 未登录 / token 失效 | HTTP 401 + {"code":-1,"msg":"用户未登录","data":{"type":"dassConsole"}} |
| gRPC 服务不可达 | {"code":-1,"msg":"服务未启动"} |
业务失败(response.Err) | {"code":<code>,"msg":"<提示>","data":"<详细错误>"} |
普通 errors.New("xxx")(无错误码) | {"code":51,"msg":"<原始错误串>"} |
| 登录失败 | {"code":-1,"msg":"账号或密码错误","data":""} |
【警告】
code=51是 GoFrame 的CodeInternalError,不是业务错误码;业务失败码是-1。客户端判失败请用code != 200,并同时容忍-1与0。
Content-Type 约定:
| 场景 | 约定 |
|---|---|
| 默认 | application/json |
| 登录 | 建议 application/x-www-form-urlencoded(JSON body 也能取到值) |
| 文件上传(点表导入、通道导入、驱动上传、表单建服务/通道) | multipart/form-data,文件字段名统一为 file |
| 文件下载 | application/octet-stream,带 Content-Disposition: attachment;filename=... |
时间格式约定:
| 场景 | 格式 | 相关接口 |
|---|---|---|
| 服务历史回补 | begin / end 为毫秒时间戳(后端除以 1000 转秒下发) | POST /config/das/data/history/{dc} |
| 操作审计 | beginTime / endTime / date 为 Unix 秒 | POST /system/operate/record |
| 通道列表 | createTime / updateTime 为毫秒 | POST /config/das/channel/list/{dc} |
| 连接 | create_time / update_time 为字符串 YYYY-MM-DD HH:MM:SS | GET /system/conn/list |
| 系统点 / 上传点(部分接口) | create_time / update_time 为 int64 | point/select、upoint/list |
2.3 鉴权
2.3.1 登录换取 token
| 项 | 值 |
|---|---|
| 方法与路径 | POST /api/mlinkClient/system/login(注册为 group.ALL,任意方法均可,推荐 POST) |
| 鉴权 | 免认证 |
| 请求字段 | login_name(账号)、password(md5(明文) 的小写 hex,32 位) |
bash
# macOS
PWD_MD5=$(md5 -q -s '<明文密码>')
# Linux
PWD_MD5=$(printf '%s' '<明文密码>' | md5sum | cut -d' ' -f1)
curl -sk -X POST "https://<控制台地址>:8095/api/mlinkClient/system/login" \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "login_name=admin" \
--data-urlencode "password=$PWD_MD5"json
{
"code": 200,
"msg": "登录成功",
"data": {
"token": "xxxxxxxx",
"user_key": "User:1",
"user_name": "管理员",
"login_name": "admin",
"status": 0,
"info": "",
"expire": 86400
}
}| 失败场景 | 响应 |
|---|---|
| 账号或密码为空 | {"code":-1,"msg":"账号或密码不能为空","data":""} |
| 用户不存在或密码错误(不区分,防枚举) | {"code":-1,"msg":"账号或密码错误","data":""} |
| 账号级锁定 | {"code":-1,"msg":"账号[admin]已被锁定,请于[xx]后重试","data":""} |
| IP 级锁定 | {"code":-1,"msg":"当前设备已被锁定,请于[xx]后重试","data":""} |
【警告】登录密码必须是
md5(明文)的小写 hex。改密接口PUT /system/user/update/password同样要求传 MD5。
2.3.2 token 的携带方式
| 场景 | 携带位置 | 建议 |
|---|---|---|
| 普通 HTTP 请求 | 请求头 Authorization: Bearer <token> | 推荐,非浏览器客户端必须显式添加 |
| HTTP 兜底 | query 或 form 参数 token=<token> | 仅在无法设置请求头时使用 |
| WebSocket 握手 | query ?token=<token> | WS 无法设置请求头,只能走 query |
| 云平台内嵌免登 | Cookie dassConsole_ticket | 【警告】二次开发不要误用该机制 |
【警告】不要依赖 Cookie 传 token。DASSConsole 自身前端是靠 localStorage 里的 token 手工加
Authorization头,Cookie 路径不可靠;dassConsole_token/auth_token只在浏览器同源场景生效。
2.3.3 token 生命周期与限制
| 项 | 值 |
|---|---|
| 有效期 | 24 小时 |
| 缓存方式 | 文件缓存,DASSConsole 重启后旧 token 可能失效 |
| 多端登录 | 允许同账号多处在线,互不踢下线 |
| 登录并发 | 全局串行(被互斥锁包裹),并发登录会互相阻塞 |
| 登录锁定 | 账号级 + IP 级双重锁定,阈值来自服务端配置 |
【警告】自动化脚本切勿暴力重试登录:账号级与 IP 级锁定会同时触发,且解锁定时间由服务端配置决定。客户端应实现「token 失效 → 自动重登一次」而不是重试循环。
2.3.4 免认证白名单
以下路径无需 token:
/api/mlinkClient/system/user/create (首次初始化建用户)
/api/mlinkClient/system/copyright/info
/api/mlinkClient/system/copyright/alter
/api/mlinkClient/stomp/info
/api/mlinkClient/topics/get
/api/mlinkClient/websocket/* (改由 WS 自身的上下文校验)
/api/mlinkClient/version/get (该分组未挂 gtoken)【注意】
version分组内唯一路由是GET /api/mlinkClient/version/get,不是/api/mlinkClient/version。
2.4 deviceCode 从哪来
{DeviceCode} 是核心链路中出现频率最高的参数,也是最容易被误解的一个。
| 项 | 结论 |
|---|---|
| 真实语义 | 控制台 sys_conn 表自增主键 ID。创建连接时,先插入记录拿到自增 ID,再把网关返回的真实设备码覆盖成该行 ID |
| 不是什么 | 不是设备盒子码、不是机器码、不是网关序列号 |
| 怎么获取 | ① GET /api/mlinkClient/system/conn/list,取 data.all.list[].deviceCode(等同 .id);② 新建连接时 POST /api/mlinkClient/system/conn/create 返回的 data.deviceCode |
| 怎么传 | 绝大多数接口是 URL 路径参数,形如 /api/mlinkClient/config/das/tree/{DeviceCode} |
| 例外(放在请求体) | DELETE /system/conn/delete、PUT /system/conn/update、POST /system/conn/cloudKey |
| 默认值陷阱 | 路径型 DeviceCode 的默认占位值是 default_0053,真机上不存在;不传会命中一条不存在的连接,报「数据不存在」 |
| ⚠️ 不存在设备的报错不一致(实测) | DeviceCode 指向不存在的连接时,读类接口返回 {code:50,"sql: no rows in result set"},但下面 7 个写/表单类接口直接 HTTP 500(exception recovered: runtime error: nil pointer dereference 或 index out of range,服务端未兜住异常) |
| 隐藏分支 | 若传入值含冒号且能切成两段(形如 host:port),服务端会按 host 查连接而不是按 deviceCode |
【警告】二次开发必须先查连接列表拿到
deviceCode,不能凭空拼;也不要在deviceCode里塞冒号。
2.5 调用前的自检清单
| # | 检查项 | 通过标准 |
|---|---|---|
| 1 | 控制台可达 | GET /api/mlinkClient/version/get 返回版本号 |
| 2 | 登录成功 | code == 200 且拿到 data.token |
| 3 | 连接存在 | GET /system/conn/list 能列出目标网关,记下 deviceCode |
| 4 | 网关在线 | 接口不返回「设备已离线,请稍后再试」或「连接超时」 |
| 5 | 驱动已安装 | POST /config/driver/list/{dc} 能看到目标驱动 |
| 6 | 驱动表单字段已知 | GET /config/driver/conf/{dc}?name=<驱动> 能拿到 para 的字段名 |
| 7 | 授权余量充足 | GET /monitor/base/{dc} 的 license_point 与 used_point 留有余量 |
帮助中心