海亮定制.md 18.6 KB

C200K

[TOC]

1. 前言

1.1 背景

方便客户基于C200K基站设备使用 通信基站数据接收及解析。

1.2 编写目的

此说明书是为了说明协议内容,开发流程,方便基于此进行二次开发。

1.3 读者对象

  1. 相关研发人员
  2. 方案制定人员
  3. 决策人员

2. 开发流程

C200K基站,采用MQTT协议进行开发,基站接入MQTT服务器,应用从MQTT服务器下发指令和接收数据

整个交互图如下:

2.1 MQTT服务器准备

MQTT服务器要求:

能够正常收发MQTT数据。

服务器的性能参数由业务决定。

域名:

公网域名或ip或者基站所处局域网ip。

MQTT服务器配置结果检查

使用MQTT.FX客户端,配置域名,端口,用户名和密码信息,然后连接,如果提示连接成功,则表示MQTT服务器可用。基站clientid 是基站编号。

2.2 基站配置

通过USB连接基站,打开基站服务器配置软件。

如果基站没有连接电脑,工具显示检测基站中,这时候读写无效。

连接正常后,按照各个信息进行写入。

设置基站服务器域名(ip)、端口,用户信息、密码信息,写入基站。

如果MQTT服务器没有启用用户密码验证,用户密码信息可以随机设置。

拔掉USB,连接网线,接入网络,查看网络是否连接正常。(基站上面的灯是否蓝色闪烁)

基站说明

软件下载

2.3 应用开发

整体开发流程图如下:

3. 功能清单

3.1 支持的功能清单

功能 说明
授时 给基站校时
基站上下线 基站上下线信息
键盘上下线 键盘上下线信息
单题 下发一题练习
多级编号题 下发多题练习
基站升级 基站固件升级
键盘升级 键盘固件升级
基站错误信息上报 基站错误信息上报

3.2 协议简介

3.2.1 MQTT

关于MQTT说明,请参考 https://mqtt.org/

${clinetId} clinetId 是基站编号,为替换字符串。

3.2.1.1 应用程序发布的主题

主题 功能
/client/${clientId}/operate 基站的设置,查询等指令
/lesson/class/${clinetId}/receive 接收答题的指令

3.2.1.2 应用程序订阅的主题

主题 功能
/client/${clientId}/online 基站上线通知。
/client/${clientId}/offline 基站下线通知。
/client/${clientId}/card/online 答题器上线通知。
/client/${clientId}/card/offline 答题器离线通知。
/client/${client}/operate 对基站进行设置或查询信息
/client/${clientId}/report 基站主动上报状态,或者对设置指令的回应。
/lesson/class/${clinetId}/receive 基站对答题的设置
/lesson/class/${clinetId}/send 基站对答题的反馈
/client/${clientId}/error 基站错误信息上报

3.2.2 协议格式

协议采用json格式,数据中字段见属性介绍。

3.2.3 指令属性介绍

名称 类型 说明
i number 消息指令类型(instruction),取值范围: 1-9999。
i = 3 添加白名单
i = 4 删除白名单
i = 5 清除白名单
i = 11 停止
i = 12开启答题
i = 13 接收答题数据
i = 14 键盘上线
i = 15 键盘下线
i = 17 基站升级
i = 18 升级报告
i = 19 授时
i = 20 设置基站信息
i = 21基站信息上报
i = 22基站错误信息上报
i = 28 键盘升级
i = 29 键盘升级报告
I= 30 读取白名单
I= 31 白名单上传
i = 40 基站上线
i = 41 基站下线
i = 60 文本预设
i = 61 文本预设返回
m object 答题消息的内容(message) 对象或数组
c string 答题器的序号(card)
t number 时间戳(10位timestamp)
qm number 模式(question model)取值范围:
0:停止
1:单题
14:多级编号答题
qt number 题型(question type),取值范围:
0:字母单选
1:字母多选
2:数字题
3:判断题
5:抢答
7: 自判题判断题
qs number 该题型数量(question sum),单题为1,多题则为实际数量。
qn number 题目序号(question No),题目顺序号
dn string display no 显示编号,键盘上显示的题目编号
a string 答案(answer)
示例:字母单选:A
字母多选:A|B|C
en string 练习(考试)编号(exercise No)每次考试或者练习的唯一编号,用于确定提交的答案属于那次练习。
on number 单选和多选题的选项数量(option no)
cid string 客户端ID(client Id)
cm string 客户端型号(client Model)
cv string 客户端版本(client Version)基站软件版本号
f number 信道频点(frequency) 基站频点取值:1-80
content string 题干内容(选项信息都包含在此),中文信息用hex进行传输。内容前面需要 hex:详见后面示例
sn string sn 序列号
et number 错误类型et =1 基站频点冲突
em string 错误消息em = "3" 配合et使用,如et=1 em=3 表示3号频点冲突
success number 0 成功 -1 错误/失败

3.3 功能说明

授时

对客户端授时,发送指令即可,基站会完成校时。


主题 : /client/${client}/operate

{
    "i": 19,
    "t": 1634802943
}
名称 备注
i = 19 授时
t 当前时间轴秒

基站管理

基站上线(待完成-可能修改)

由基站发给应用程序,应用需要订阅主题


主题 : /client/${clientId}/online


指令内容:

{
    "i": 40
} 
名称 备注
i = 40 基站上线

基站下线(待完成-可能修改)

由服务器发给应用程序,应用需要订阅主题


主题:/client/${clientId}/offline
指令内容:

{ 
    "i": 41
} 
名称 备注
i = 41 基站下线

基站信息设置与读取

应用程序发送给基站


主题: /client/${client}/operate
指令内容:

{
    "i": 20,
    "m": {
        "f": 1,
        "mqtt_ip": "edunew.sunvotecloud.cn",
        "mqtt_port": 1883,
        "mqtt_username": "admin",
        "mqtt_password": "1223456789"
    }
}
名称 备注
i= 20 基站信息设置与读取
f 基站频点 频点范围1-80
mqtt_ip 连接服务器的IP
mqtt_port 连接mqtt服务器的端口
mqtt_username 连接mqtt服务器的用户名
mqtt_password 连接mqtt服务器的密码
注意 如果没有该字段则不设置该值,保持原值下发对有需要修改的值设置完成后,基站信息会自动上报一次

基站信息上报

基站发送给应用程序


主题: /client/${client}/report
指令内容:

{
    "i": 21,
    "cId": "2024010282",
    "m": {
        "f": 1,
        "mqtt_ip": "edunew.sunvotecloud.cn",
        "mqtt_port": 1883,
        "mqtt_username": "admin",
        "mqtt_password": "1223456789"
    }
}
名称 备注
i= 21 基站信息上报
cId 客户端ID
f 基站频点
mqtt_ip 连接服务器的IP
mqtt_port 连接mqtt服务器的端口
mqtt_username 连接mqtt服务器的用户名
mqtt_password 连接mqtt服务器的密码

基站错误信息上报(待完成-可能修改)

基站发送给应用程序主题
主题:/client/${client}/error
指令内容:

{
    "i": 22,
    "m": {
        "et": 1,
        "em": "3"
    }
}
名称 备注
i = 22 基站错误信息上报
et 错误类型 et = 1 :基站频点冲突
em 错误消息 em=3 :3号频点示例 基站频点3冲突

键盘管理

键盘上线

由基站发给应用程序,应用需要订阅主题
主题: /client/${clientId}/card/online
指令内容:

{
    "i": 14,
    "m": [{
        "c": "2126833671",
        "t": 1626016299
    }]
}
名称 备注
i = 14 键盘上线
c 键盘sn号

键盘下线

由基站发给应用程序,应用需要订阅主题
主题: /client/${clientId}/card/offline
指令内容:

{
    "i": 15,
    "m": [{
        "c": "2126833671",
        "t": 1626016299
    }]
}
名称 备注
i = 15 键盘下线
c 键盘sn号
t 答题器编号和下线时间

读取白名单

应用程序发送给基站
主题: /lesson/class/${clinetId}/receive
指令内容:

{
    "i": 30
}
名称 备注
i = 30 读取白名单

基站发给应用程序主题
主题: /lesson/class/${clinetId}/receive
指令内容:

{
    "i": 31,
    "total": 1,
    "current": 1,
    "m": ["2126932551"]
}
名称 备注
i = 31 白名单上传
total 一共上传的数据包数
current 当前第几包
m 键盘序列号列表

添加白名单

应用程序发送给基站
主题: /lesson/class/${clinetId}/receive
指令内容:

{
    "i": 3,
    "m": ["2126833703", "2126833671"]
}
名称 备注
i = 3 添加白名单m内包含白名单键盘按编号
m 键盘序列号列表

删除白名单

应用程序发送给基站
主题: /lesson/class/${clinetId}/receive
指令内容:

{
    "i": 4,
    "m": ["2126833703", "2126833671"]
}
名称 备注
i = 4 删除白名单m内包含白名单键盘按编号
m 键盘序列号列表

清空白名单

应用程序发送给基站
主题: /lesson/class/${clinetId}/receive
指令内容:

{
    "i": 5
}
名称 备注
i = 5 清空白名单

单题

开启答题

由应用程序发给基站,应用按照主题发送
主题: /lesson/class/${clinetId}/receive
指令内容:

{
    "i": 12,
    "en": "1",
    "qm": 1,
    "m": {
        "qt": 0,
        "on": 4,
        "content": "hex:d5c5c8fd"
    }
}
名称 备注
i = 12 下发答题
en 序号
qm = 1 单题模式 示例为单题模式的字母单选
qt 字母单选
on 选项数
content = 1 题目主干内容,hex: 为内容的GBK编码的hex内容

System.out.println(new String(hex2Bytes(bytesToHexString("李四".getBytes("GBK"))),"GBK"));

public static String bytesToHexString(byte[] src) {
    StringBuilder stringBuilder = new StringBuilder("");
    if (src == null || src.length <= 0) {
        return "";
    }
    for (int i = 0; i < src.length; i++) {
        int v = src[i] & 0xFF;
        String hv = Integer.toHexString(v);
        if (hv.length() < 2) {
            stringBuilder.append(0);
        }
        stringBuilder.append(hv);
        stringBuilder.append("");
    }
    return stringBuilder.toString();
}

 public static byte[] hex2Bytes(String hex){
    if(hex.length() % 2 == 0){
        byte[] ret = new byte[hex.length() / 2];
        for(int i = 0 ; i< hex.length() / 2 ; i++){
            ret[i] = (byte)Integer.parseInt(hex.substring(2*i,2*i+2),16);
        }
        return ret;
    }
    return null;
}

接收答题数据

由基站发给应用程序,应用订阅主题
主题: /lesson/class/${clinetId}/send

指令内容:

{
    "i": 13,
    "en": "1",
    "qm": 1,
    "c": "2126833671",
    "m": [{
        "qn": 1,
        "a": "A",
        "t": 1626016299
    }]
}
名称 备注
i = 13 答题数据
qn 上报答题数据,单题题号固定为1
t 提交答案时间
a 答题数据

停止答题

由应用程序发给基站,应用按照发送
主题:/lesson/class/${clinetId}/receive
指令内容:

{
    "i": 11,
    "en": "1"
}
名称 备注
i = 11 停止答题
en 停止对序号1的练习

抢答

开启答题

由应用程序发给基站,应用按照发送
主题: /lesson/class/${clinetId}/receive
指令内容:

{
    "i": 12,
    "en": "2",
    "qm": 4
}
名称 备注
i = 12 开启答题
en 序号2的练习
qm qm =4 抢答题

接收答题数据

由基站发给应用程序,应用订阅
主题: /lesson/class/${clinetId}/send
指令内容:

{
    "i": 13,
    "en": "2",
    "qm": 4,
    "m": [{
        "c": "2126833671",
        "t": 1626016299
    }]
}
名称 备注
i = 12 开启答题
en 序号2的练习
qm qm =4 抢答题
c 键盘编号
qn 上报答题数据,单题题号固定为1
t 提交答案时间
a 答题数据

停止答题(待完成-可能修改)

由应用程序发给基站,应用按照主题发送
主题:/lesson/class/${clinetId}/receive
指令内容:

{
    "i": 11,
    "en": "2"
}
名称 备注
i = 11 停止答题
en 停止对序号2的练习

多题题号多题

开启答题

由应用程序发给基站,应用按照主题发送
主题: /lesson/class/${clinetId}/receive
指令内容:

{
    "i": 12,
    "en": "3",
    "qm": 14,
    "total": 1,
    "current": 1,
    "qs": 3,
    "m": [{
        "qt": 0,
        "on": 4,
        "dn": "1-1-1"
    }, {
        "qt": 0,
        "on": 4,
        "dn": "2-1"
    }, {
        "qt": 0,
        "on": 4,
        "dn": "3"
    }]
}
名称 备注
i = 12 开启答题
en 12341练习
qm = 14 多题多级编号模式
current 当前第几包数据
total 一共几包数据
qs 题目总数
qt = 0 字母单选
on 选项数量
dn 显示编号,题目最多3级数字编号,多级数字编号中间必须以“-”隔开,每级最大数200

接收答题数据

由基站发给应用程序,应用订阅主题
主题: /lesson/class/${clinetId}/send
指令内容:

{
    "i": 13,
    "en": "3",
    "qm": 14,
    "c": "2126833671",
    "m": [{
        "qn": 1,
        "a": "A",
        "t": 1626016299
    }]
}
名称 备注
i = 13 接收答题数据
en 12341练习
qm = 14 多题多级编号模式
c 键盘编号
qn 顺序题号,不为显示编号,是上述题目的顺序号
t 提交答案时间
a 答题数据

停止答题

由应用程序发给基站,应用按照主题发送
主题:/lesson/class/${clinetId}/receive
指令内容:

{
    "i": 11,
    "en": "3"
}
名称 备注
i = 11 停止答题
en 停止对序号12341的练习

基站升级

开始升级


主题: /client/${client}/operate
指令内容:

{
    "i": 17,
    "en": "5",
    "m": {
        "url": "",
        "version": "",
        "CRC": ""
    }
}
名称 备注
i = 17 基站升级
en 序号5
url 固件包地址,基站能访问到的路径
version 新固件的版本
CRC 新关键计算的CRC

升级进度报告


主题: /client/${client}/report
指令内容:

{
    "i": 18,
    "m": {
        "cId": "3411111156",
        "percent": 0,
        "status": 0
    }
}
名称 备注
i = 18 升级进度报告
cId 基站编号
percent 升级百分比
status 升级状态信息。
0:未开始
1:升级中
2:升级成功
4:固件版本号错误
5:不在升级名单内
6:升级指令错误
>127:升级中的错误码。

键盘升级

开始升级


主题: /client/${client}/operate
指令内容:

{
    "i": 28,
    "m": {
        "url": "http://120.78.57.84:8888/file/S6_2.4G_2.1.2.50_GB2312_CGC_add_head.bin",
        "version": "2.1.2.50",
        "CRC": "10605263"
    }
}
名称 备注
i = 28 键盘升级
url 固件包地址,基站能访问到的路径
version 新固件的版本号
CRC 新关键计算的CRC

升级进度报告


主题: /client/${client}/report
指令内容:

{
    "i": 29,
    "m": {
        "cId": "2023065218",
        "percent": 0,
        "status": 0
    }
}
名称 备注
i = 29 升级进度报告
cId 基站编号
percent 升级百分比
status 升级状态信息。
0:未开始
1:升级中
2:升级成功
4:固件版本号错误
5:不在升级名单内
6:升级指令错误
>127:升级中的错误码。

文本下发

文本下发


主题: /lesson/class/${clinetId}/receive
指令内容:

{
    "i": 60,
    "en": "6",
    "cmd": 1,
    "total": 1,
    "current": 1,
    "m": [{
        "sn": "2126833671",
        "text": "hex:d5c5c8fd"
    },{
        "sn": "2126833672",
        "text": "hex:c0eecbc4"
    }]
}
名称 备注
i = 60 文本下发
sn 键盘列表
current 当前第几包
total 一共多少包
cmd 下发的命令
1: 姓名下发
4: 第二行文本
85: 自判题判断
87: 清除
text 标题信息,以hex:开头添加的内容 内容为GBK的hex编码

 System.out.println(bytesToHexString("李四".getBytes("GBK")));

 public static String bytesToHexString(byte[] src) {
    StringBuilder stringBuilder = new StringBuilder("");
    if (src == null || src.length <= 0) {
        return "";
    }
    for (int i = 0; i < src.length; i++) {
        int v = src[i] & 0xFF;
        String hv = Integer.toHexString(v);
        if (hv.length() < 2) {
            stringBuilder.append(0);
        }
        stringBuilder.append(hv);
        stringBuilder.append("");
    }
    return stringBuilder.toString();
}

文本下发返回


主题: /lesson/class/${clinetId}/send
指令内容:

{
    "i": 61,
    "en": "6",
    "cmd": 1,
    "total": 1,
    "current": 1,
    "m": [{
        "sn": "2126833671",
        "success": 0
    }]
}
名称 备注
i = 61 文本下发返回
sn 键盘号
current 当前第几包
total 一共多少包
cmd 下发的命令
1: 姓名下发
4: 第二行文本
85:自判题判断
87:清除
success 是否成功。
0 表示成功
-1 失败

学生卡信息上报

卡初始化组网的时候会上报一次
主题:/client/${client}/report
指令内容:

{
    "i":32,
    "m":[
        {
            "c":"1873373905",
            "cv":"0.2.2",
            "hw":"67.0",
            "t":1638865040
        }
    ]
}
名称 备注
i = 32 学生卡信息上报
c 键盘编号
cv 固件版本号
hw 硬件版本号
t 时间戳