终端机MQTT通讯协议
终端机MQTT通讯协议
简介
终端程序支MQTT方式,该协议是终端设备主动连接MQTT消息服务器,然后服务器端也连接该MQTT服务器,通过发布订阅的方式进行交互,是目前非常流行的物联网接入方式,xx推荐,该通讯方式不依赖于任何程序或者组件,所以可以在Linux下接入设备。
协议说明
在浏览器中输入xxxx://xxxXX 进入终端机配置页面
联机配置→选择MQTT协议→输入服务器信息,如图:
注:Topic前缀属于个性功能,将会覆盖默认的【jdev】
设备连接到MQTT服务后,将发送上线消息。
服务器收到上线消息后添加到自己的业务系统中。
服务器发送档案等数据到设备的订阅中,完成下发。
终端设备将产生的记录和消息通过指定topic发送。
该文档内置在终端机服务中,随不同终端机类型展现也会有少许不同。
文档是Rest格式,MQTT通过组织特定格式可以调用Rest接口。
查看方法:
【进入设备管理】→【联机设置】→【查看API】
返回值含义:
交互消息
用于下发档案、设置设备等功能,详见【协议文档】章节
注:从未上线的终端给他发送消息会丢失。上线过的终端MQTT服务将会持久化设备的通道数据,即使离线也不会丢失数据。
服务器发布的Topic主题
只写 |
jdev/att/设备ID/api |
发布到指定的设备ID及应用 |
只写 |
jdev/att/all/api |
发布到所有设备中指定的应用 |
例:jdev/att/12345/api
服务器发布消息demo:
{ // 接口名,同RESTful接口的名字 "api": "/config/set_time",
// 应答ID,省略后不应答 // "sAckId":"abcd1234",
// 接口的其他参数,并行写出,比如下面就是设置时间的时间参数: "timeStr": "2019-12-31 13:46:32" } |
服务器发布大消息(消息文件):
如果需要发送的数据太多,MQTT显然是不适合的,这时候可以将数据以JSON形式组合成文件或者接口,然后通过发送:
{ // JSON文件URL(也可以是接口),将会使用GET拉取 "cmdDataUrl":"xxxx://00.0.00.00:0000/xxxx.xxxx" } |
终端收到数据后将从cmdDataUrl中拉取具体指令,然后执行
注:可以混合其他参数,这些参数将合并到远程拉取的json里
客户端应答
注:如果参数中含有sAckId(一个随机字符串),终端在处理完消息后会将指令的返回结果(例如:获取终端信息的接口)送往MQTT服务,应答Topic为:
只读 |
jdev/att/设备ID/api_ret |
终端设备应答数据 |
例:jdev/att/12345/api_ret
终端发布
用于记录上传、消息上传等,详见【上传示例】章节
终端设备发布的消息格式demo:
{ // 类型 msgType: "xxx", // 终端机要上传的数据 "xxxx": "xxxx" } |
下发示例
下发所有档案
该操作将清空所有现存档案,属于全量下发。
(只写)topic示例:jdev/att/all/api
参数 |
数据类型 |
是否必需 |
描述 |
|
api |
String |
是 |
/att/white_list |
|
isPart |
String |
是 |
为false表示先清除原有的数据,再新增名单内容 |
|
baseUrl |
String |
是 |
基础URL路径,url如果省略了http则添加该部分 |
|
list |
List |
是 |
人员列表 |
|
|
i |
Integer |
是 |
人员编号 |
|
n |
String |
是 |
姓名,删除的时候可省 |
|
u |
String |
否 |
工号 |
|
c |
String |
否 |
卡号,省略=无卡号 |
|
b |
String |
否 |
生日 |
|
w |
String |
否 |
密码 |
|
d |
String |
否 |
部门名称 |
|
m |
String |
否 |
门禁规则,需要匹配门禁规则(对应门禁里面的gz字段) |
|
tb |
String |
否 |
有效期开始 |
|
te |
String |
否 |
有效期结束 |
|
p |
String |
否 |
档案照片。可使用base64图片格式,省略或null=无照片,2=维持原有 |
|
f |
String |
否 |
人脸照片。可使用base64图片格式,省略或null=无人脸,1=人脸为档案照片,2=维持原有 |
数据示例 |
//将张三下发到所有设备,人脸和档案照片使用同一个URL图片: { "api":"/att/white_list", "isPart": false, "baseUrl": "xxxx://00.0.00.00:0000/", "list": [ { "i": 200001, "n": "xx", "u": "A01Z3", "c": "0A0366B0", "b": "2019-07-30", "w": "123456", "d": "部门名称", "tb": "2019-07-29 00:00:00", "te": "2059-07-30 23:59:59", "p": "photo/200001.jpg", "f": "1" } ] } |
新增档案
(只写)topic示例: jdev/att/5394611/api
参数 |
数据类型 |
是否必需 |
描述 |
|
api |
String |
是 |
/att/white_list |
|
isPart |
String |
是 |
为false表示先清除原有的数据,再新增名单内容 |
|
baseUrl |
String |
是 |
基础URL路径,url如果省略了http则添加该部分 |
|
list |
List |
是 |
人员列表 |
|
|
i |
Integer |
是 |
人员编号 |
|
t |
Integer |
是 |
类型/省略或=1为新增或者修改。3=删除 |
|
n |
String |
是 |
姓名,删除的时候可省 |
|
u |
String |
否 |
工号 |
|
c |
String |
否 |
卡号,省略=无卡号 |
|
b |
String |
否 |
生日 |
|
w |
String |
否 |
密码 |
|
d |
String |
否 |
部门名称 |
|
m |
String |
否 |
门禁规则,需要匹配门禁规则(对应门禁里面的gz字段) |
|
tb |
String |
否 |
有效期开始 |
|
te |
String |
否 |
有效期结束 |
|
p |
String |
否 |
档案照片。可使用base64图片格式,省略或null=无照片,2=维持原有 |
|
f |
String |
否 |
人脸照片。可使用base64图片格式,省略或null=无人脸,1=人脸为档案照片,2=维持原有 |
数据示例 |
//将xx下发到5394611设备,人脸和档案照片使用同一个URL图片: { "api":"/att/white_list", "isPart": true, "baseUrl": "xxxx://00.0.00.00:0000/", "list": [ { "t": 1, "i": 200002, "n": "xx", "u": "A01Z3", "c": "0A0366B0", "b": "2019-07-30", "w": "123456", "d": "部门名称", "tb": "2019-07-29 00:00:00", "te": "2059-07-30 23:59:59", "p": "photo/200002.jpg", "f": "1" } ] } |
删除档案
(只写)topic示例: jdev/att/all/api
参数 |
数据类型 |
是否必需 |
描述 |
|
api |
String |
是 |
/att/white_list |
|
isPart |
String |
是 |
为false表示先清除原有的数据,再新增名单内容 |
|
baseUrl |
String |
是 |
基础URL路径,url如果省略了http则添加该部分 |
|
list |
List |
是 |
人员列表 |
|
|
i |
Integer |
是 |
人员编号 |
|
t |
Integer |
是 |
类型/省略或=1为新增或者修改。3=删除 |
|
n |
String |
是 |
姓名,删除的时候可省 |
|
u |
String |
否 |
工号 |
|
c |
String |
否 |
卡号,省略=无卡号 |
|
b |
String |
否 |
生日 |
|
w |
String |
否 |
密码 |
|
d |
String |
否 |
部门名称 |
|
m |
String |
否 |
门禁规则,需要匹配门禁规则(对应门禁里面的gz字段) |
|
tb |
String |
否 |
有效期开始 |
|
te |
String |
否 |
有效期结束 |
|
p |
String |
否 |
档案照片。可使用base64图片格式,省略或null=无照片,2=维持原有 |
|
f |
String |
否 |
人脸照片。可使用base64图片格式,省略或null=无人脸,1=人脸为档案照片,2=维持原有 |
数据示例 |
//将xx从所有设备中删除: { "api":"/att/white_list", "isPart": true, "list": [ { "t": 3, "i": 200001 } ] } |
远程开门
(只写)topic示例: jdev/att/5394611 /api
参数 |
数据类型 |
是否必需 |
描述 |
api |
String |
是 |
/att/cmd |
cmd |
String |
是 |
openDoor 远程开门 |
keepMs |
Integer |
否 |
1000 表明开门的持续时间 |
数据示例 |
//远程开门5394611设备 { "api": "/att/cmd", "cmd": "openDoor", "keepMs": 100 }
|
门禁规则
(只写)topic示例: jdev/att/5394611/api
参数 |
数据类型 |
是否必需 |
描述 |
||
api |
String |
是 |
/att/mj_rule |
||
mjsd |
List |
是 |
门禁时段列表 |
||
|
sd |
Integer |
是 |
时段号 |
|
|
yb |
String |
是 |
有效期开始 |
|
|
ye |
String |
是 |
有效期结束 |
|
|
mb |
Integer |
是 |
月份开始 |
|
|
me |
Integer |
是 |
月份结束 |
|
|
db |
Integer |
是 |
日份开始 |
|
|
de |
Integer |
是 |
日份结束 |
|
|
wb |
Integer |
是 |
星期开始 |
|
|
we |
Integer |
是 |
星期结束 |
|
|
tb |
String |
是 |
时间开始 |
|
|
te |
String |
是 |
时间结束 |
|
mjgz |
List |
是 |
规则对应时段列表 |
||
|
gz |
Integer |
是 |
规则号(对应下发白名单的m字段) |
|
|
sd |
String |
是 |
规则所包含的时段 |
|
wdmj |
List |
是 |
高级规则 |
||
|
keepOpen |
Integer |
是 |
常开规则 |
|
|
keepClose |
Integer |
是 |
常闭规则 |
|
数据示例 |
{ "api": "/att/mj_rule", "mjsd": [ { "sd": 1, "yb": "2000-01-01", "ye": "2018-12-31", "mb": 1, "me": 12, "db": 1, "de": 31, "wb": 1, "we": 7, "tb": "00:00:00", "te": "23:59:59" }, { "sd": 2, "yb": "2018-12-31", "ye": "2059-12-31", "mb": 1, "me": 12, "db": 1, "de": 31, "wb": 1, "we": 7, "tb": "00:00:00", "te": "23:59:59", } ], "mjgz": [ { "gz": 1001, "sd": "1,2", } ], "wdmj": { "keepOpen": 0, "keepClose": 0, }
} |
||||
|
|
通知公告
(只写)topic示例: jdev/att/5394611/api
参数 |
数据类型 |
是否必需 |
描述 |
|
api |
String |
是 |
/att/notice |
|
list |
List |
是 |
公告数据列表 |
|
|
title |
String |
是 |
标题 |
|
body |
String |
是 |
公告内容(第一行\n第二行) |
|
publisher |
String |
是 |
发布者 |
|
time |
String |
是 |
公告显示日期 |
|
timeEnd |
String |
是 |
公告结束显示日期 |
数据示例 |
{ "api": "/att/notice", "list": [ { "title": "标题", "body": "第一行\n第二行", "publisher": "发布者1", "time": "2019-09-02 15:30:00", "timeEnd": "2059-09-02 23:59:59" }, { "title": "标题2", "body": "第1行\n第2行", "publisher": "发布者2", "time": "2019-09-02 15:30:00" } ] } |
待机媒体
(只写)topic示例: jdev/att/5394611/api
参数 |
数据类型 |
是否必需 |
描述 |
|
api |
String |
是 |
/att/media |
|
baseUrl |
String |
是 |
基础url路径 |
|
List |
List |
是 |
数据列表 |
|
|
type |
int |
否 |
0=图片,5=视频 |
|
url |
String |
是 |
文件url或基于baseUrl |
数据示例 |
{ "api": "/att/media", "baseUrl": "xxxx://00.0.00.00:0000/", "list": [ { "type": 0, "url": "media/pic_1.jpg" }, { "type": 0, "url": "media/pic_2.jpg" } ] |
临时人员
(只写)topic示例: jdev/att/5394611/api
参数 |
数据类型 |
是否必需 |
描述 |
|
api |
String |
是 |
/att/temp_list |
|
isPart |
Boolean |
是 |
为false表示先清除原有的数据,再新增名单内容 |
|
baseUrl |
String |
是 |
基础URL路径,url如果省略了http则添加该部分 |
|
list |
List |
是 |
人员列表 |
|
|
i |
Integer |
是 |
人员编号 |
|
n |
String |
是 |
姓名 |
|
u |
String |
是 |
工号 |
|
c |
String |
是 |
卡号,省略=无卡号 |
|
d |
String |
是 |
部门名称 |
|
tb |
String |
是 |
有效期开始 |
|
te |
String |
是 |
有效期结束 |
|
f |
String |
是 |
人脸照片。可使用base64图片格式,省略或null=无人脸,1=人脸为档案照片,2=维持原有 |
数据示例 |
{ "api":"temp_list", "isPart": false, "baseUrl": "xxxx://00.0.00.00:0000/", "list": [ { "i": 200013, "n": "UserName", "u": "A01Z3", "c": "C15DEFD3", "d": "DepName", "tb": "2019-07-29 00:00:00", "te": "2059-07-30 23:59:59", "f": "photo/20000003.jpg" } ] }
|
上传示例
设备心跳
(只读)topic示例: jdev/att/5394611/heart
参数 |
数据类型 |
是否必需 |
描述 |
|
msgType |
String |
是 |
消息类型 |
|
mqTime |
String |
是 |
mq时间 |
|
appInfo |
Object |
是 |
app信息 |
|
|
taskCount |
Integer |
是 |
剩余任务数 |
|
docCount |
Integer |
是 |
档案数 |
|
faceCount |
Integer |
是 |
人脸数 |
|
remainRecord |
Integer |
是 |
未上传记录数 |
|
remainOplog |
Integer |
是 |
未上传操作日志数 |
sigState |
Object |
是 |
档案标记 |
|
|
lastDocSig |
String |
是 |
最后接收到的档案标记 |
|
docSig |
String |
是 |
当前档案标记 |
数据示例 |
{ "msgType": "heart", "mqTime": "2020-10-20 10:11:41", "appInfo": { "taskCount": 0, "docCount": 1, "faceCount": 1, "remainRecord": 0, "remainOplog": 0 }, "sigState": { "lastDocSig": "", "docSig": "" } } |
注:档案标记是在下发档案时的serDocSig字段,可以不使用。
记录上传
(只读)topic示例: jdev/att/5394611/record
参数 |
数据类型 |
是否必需 |
描述 |
|
msgType |
String |
是 |
消息类型 |
|
user |
Integer |
是 |
用户ID |
|
time |
String |
是 |
时间 |
|
auth |
String |
是 |
认证方式:i=编号,p=密码,c=刷卡,f=指纹,l=人脸(组合用+) |
|
group |
Integer |
是 |
0=继电器未动作,1=继电器动作 |
|
logId |
String |
是 |
日志流水 |
|
card |
String |
是 |
卡号(如果有) |
|
type |
Integer |
是 |
日志类型,18=无权限,45=成功 |
|
senTemp |
Integer |
是 |
表面温度(0=采集失败,无字段=不支持) |
|
bodyTemp |
Integer |
是 |
体温(0=采集失败,无字段=不支持) |
|
facePosition |
Object |
是 |
人脸坐标(无字段=不支持) |
|
x |
|
Integer |
是 |
X坐标 |
y |
|
Integer |
是 |
Y坐标 |
w |
|
Integer |
是 |
宽度 |
h |
|
Integer |
是 |
高度 |
photo |
String |
是 |
照片数据 |
|
数据示例 |
{ msgType: "record", user: 123456, time: "2019-09-25 11:08:27", auth: "l", group: "1", logId: 100, card: "AABBCCDD", type: 45, senTemp: 34.5, bodyTemp: 36.5, facePosition: { x: 123, y: 456, w: 100, h: 101 }, photo: "image/jpeg;base64,xxxxxxxxxxxxx"} |
消息上传
(只读)topic示例: jdev/att/5394611/message
参数 |
数据类型 |
是否必需 |
描述 |
user |
Integer |
是 |
0=成功,否则失败 |
msgType |
String |
是 |
消息类型 |
time |
String |
是 |
时间 |
type |
String |
是 |
消息类型。fe=人脸处理错误,ad=新增档案,af=录入指纹,uk=发卡,ap=录照片。这些功能都需要设备的支持 |
param |
String |
是 |
参数:fe和-4000=找不到人脸,fe和-4001=不合格的人脸 |
数据示例 |
{ "user": 123456, "time": "2019-09-25 11:08:27", "type": "fe", "param": "-4001" } |
身份证记录上传
(只读)topic示例: jdev/att/5394611/rec_iden
参数 |
数据类型 |
是否必需 |
描述 |
|
MsgType |
Integer |
是 |
消息类型 |
|
time |
String |
是 |
时间 |
|
state |
Integer |
是 |
1=通过,2=失败,3=无效,4=证件失效 |
|
sfzCode |
String |
是 |
身份证号 |
|
sfzName |
String |
是 |
身份证姓名 |
|
sfzSex |
String |
是 |
身份证性别 |
|
sfzNation |
String |
是 |
身份证民族 |
|
sfzAddress |
String |
是 |
身份证地址 |
|
sfzValid |
String |
是 |
身份证有效期 |
|
phone |
String |
是 |
手机号 |
|
beVisit |
String |
是 |
被访问 |
|
healthArea |
String |
是 |
健康码地区 0=北京,1=山东 |
|
healthCode |
String |
是 |
健康码状态 |
|
senTemp |
Integer |
否 |
表面温度 |
|
bodyTemp |
Integer |
否 |
体温 |
|
facePosition |
Object |
否 |
人脸坐标(无字段=不支持) |
|
|
x |
Integer |
是 |
x坐标 |
|
y |
Integer |
是 |
y坐标 |
|
w |
Integer |
是 |
宽度 |
|
h |
Integer |
是 |
高度 |
photo |
String |
是 |
照片数据 |
|
数据示例 |
{ "msgType": "rec_iden", "time": "2019-09-25 11:08:27", "state": 1, "sfzCode": "3XXXXXXXXXX", "sfzName": "xx", "sfzSex": "男", "sfzNation": "汉", "sfzAddress": "xxxxxx", "sfzValid": "20190930-20390930", "phone": "00000000000", "beVisit": "xx", "healthArea": "0" "healthCode": "0" "senTemp": 34.5, "bodyTemp": 36.5, "facePosition": { "x": 123, "y": 456, "w": 100, "h": 101 }, "photo": "image/jpeg;base64,xxxxxxxxxxxxx" }
|