移动讲台协议
# 1. 移动讲台
## 1.1. 功能目标
白板与移动讲台app间通信协议
## 1.2. 名称解析
| 名称 | 说明 | 其他 |
| ------ | ----------------- | ---- |
| 服务端 | 白板开启的TCP服务 | 无 |
| 客户端 | 移动讲台APP | 无 |
## 1.3. 流程
1. 白板指令流程

2. 移动讲台指令流程

3. 图片浏览器
> 1、开启批注后发送批注view的宽高给接收端
> 2、批注的坐标定位使用view的中心点偏移量(防止由于发送端接收端view的尺寸不一致引起批注位置偏移)
> 3、接收端收到批注的坐标后需要根据发送端的view的搞度与接收端view的高度对坐标进行换算
> 4、第3步中换算得出批注点在接收端相对view中心的点偏移量,还原出接收端批注点在接收端的实际坐标进行绘制
> 5、聚光灯的坐标也与批注点坐标进行相同的换算
4. AI助手流程

## 1.4. 协议主体
### 1.4.1. 基础
| 内容 | 详细说明 |
| ---------- | ------------------------------------------ |
| 字符编码 | utf-8 |
| 内存字节序 | 高位编址。例:`0x00 01`(1),`0x01 00`(256) |
| `null` | 置空 |
| `\` | 文本分割符 |
| *斜体内容* | 待定内容 |
### 1.4.2. 帧
| 内容 | 详细说明 |
| ------ | ------------------------------- |
| 帧格式 | 帧长(4byte)+帧内容(不定长) |
| 帧内容 | 帧类型(byte)+帧实际内容(不定长) |
### 1.4.3. 错误重连
| 错误 | 解决方式 |
| ------------------ | -------------------------- |
| 服务器收到错误数据 | 断开对应客户端,客户端重连 |
| 客户端收到错误数据 | 断开连接,重连 |
| 网络错误 | 客户端定时重连 |
### 1.4.4. UDP广播
1. pc端作为client发送广播,android作为server接收广播
2. 广播内容为格式如下的String:“UBCC\班级名称\ip\port\连接密码”
3. 未设置连接密码时内容为:“UBCC\班级名称\ip\port”
### 1.4.5. 屏幕同步(独立的一个SOKCET连接)
#### 1.4.5.1. 指令
- ANDROID
| 代码 | 定义 | 具体内容 |
| ---- | ------------------------- | ----------------------------------- |
| 0x10 | 请求传屏到pc | |
| 0x11 | android端主动结束传屏 | |
| 0x12 | 请求pc传屏到android | android端渲染view的高度int(4个Byte) |
| 0x13 | android端主动结束接收传屏 | |
- PC
| 代码 | 定义 | 具体内容 |
| ---- | -------------------- | ----------------------------------- |
| 0x1D | pc端主动结束接收传屏 | |
| 0x1E | 允许android传屏到pc | ip+port(pc端接收传屏的端口) |
| 0x1F | 拒绝android传屏到pc | |
| 0x1A | pc端主动结束传屏 | |
| 0x1B | 允许传屏到android | ip+port(pc端发送传屏的服务器的端口) |
| 0x1C | 拒绝传屏到android | |
#### 1.4.5.2. 视频帧内容
| 代码 | 定义 | 具体内容 |
| ---- | ---------- | ---------------------------------- |
| 0x10 | 视频帧内容 | 帧类型(Byte)+H.264编码的视频帧数据 |
### 1.4.6. 文件传输(独立的一个SOKCET连接)
#### 1.4.6.1. 发送端(PC->ANDROID OR ANDROID->PC)
| 代码 | 定义 | 具体内容 |
| ---- | -------------------------- | ------------------------------------------------------------- |
| 0xAA | 文件发送片段完成 |一次性发送多个片段完成后发送指令
| 0xBB | 文件接收片段完成 |接收到0xAA指令后的响应
| 0x01 | 请求发送文件 |打开定义[打开文件的具体内容](#openfile) |
| 0x02 | 所有文件发送开始 | 所有文件的文件名(文件路径之间以`"*"`分割) |
| 0x03 | 文件信息(单个文件发送开始) | 文件路径字节长度(int)+文件路径(string)+文件名包含后缀(string) |
| 0x04 | 发送单个文件内容 | 文件路径字节长度(int)+文件路径(string)+文件数据(ByteArray) |
| 0x05 | 发送单个文件结束 | 文件路径(string) |
| 0x06 | 所有文件发送结束 | 打开定义[打开文件的具体内容](#openfile) |
#### 1.4.6.2. 接收端(PC->ANDROID OR ANDROID->PC)
| 代码 | 定义 | 具体内容 |
| ---- | -------- | -------- |
| 0x10 | 接收成功 | 文件名 |
| 0x11 | 接收失败 | 文件名 |
#### 1.4.6.3. 打开文件
附:打开文件的具体内容<a name="openfile"></a>
| 代码 | 定义 | 后续内容 |
| ---- | ---------- | -------------------------------------------- |
| 0x00 | 常规文件 | 文件在已发送的文件列表中的index(int 4个字节) |
| 0x01 | 图片 | 图片在已发送的图片列表中的index(int 4个字节) |
| 0x02 | 视频 | 视频在已发送的图片列表中的index(int 4个字节) |
| 0xa1 | 文件胶囊图片缩略图 | |
| 0xa2 | 文件胶囊文件 | |
| 0xe0 | 白板预览图 | |
| 0xe1 | PPT预览图 | |
| 0xfe | 转发 | 对应学生ID |
| 0xff | 无操作 | 注:仅在传送完成时不作打开操作时用 |
### 1.4.7. 主指令通道
#### 1.4.7.1. 基本信息
1. Andorid
| 名称 | 定义 | 具体内容 |
| ---- | -------- | -------- |
| 0x00 | 查询状态 | |
2. PC
| 名称 | 定义 | 具体内容 |
| ---- | -------- | --------------------------------------------------------------------------------- |
| 0x00 | 返回状态 | 总页数(short),当前页(short),工具状态(2个int型,按位算),互动课堂工具状态(2个int型),登录云状态(byte:0-未登录,1-登录),服务器地址长度(int),服务器地址(string),**{帐号字节长度(int),帐号(string未登录没有);token长度(int),token(string) **//没有登录时没有这些数据**}** |
| 0x0F | 返回状态 | 0x00登录成功</br>0xff登录失败 |
#### 1.4.7.2. 演示
##### 1.4.7.2.1. 白板操作(Android)
| 名称 | 定义 | 具体内容 |
| ---- | ------------------------ | ----------------------------------------------------- |
| 0x2f | 翻页 | 上一页:0x01<br>下一页:0x02<br>跳转:0x03+页码(byte) |
| 0x20 | 请求预览图 | 本机分辨率W(int),H(int) |
| 0x21 | 切换笔类型 | 0x01:普通笔<br>0x02:激光笔<br>0x03:橡皮擦 |
| 0x22 | 切换普通笔颜色 | 0x01蓝色<br>0x02黄色<br>0x03红色<br>0x04黑色<br>0x05白色 |
| 0x23 | 修改普通笔宽度 | 0x01小<br>0x02中<br>0x03大 |
| 0x24 | 鼠标/触屏事件(按下/释放) | 见[按下/释下](#pointmove) |
| 0x25 | 单/多点移动事件(移动) | 见[移动](#multipoint) |
|0x26|页面操作|0x01:新建页,0x02:删除页,0x03:清空页,0x04:复制页,0x10:撤消,0x11:恢复,0x20:保存|
|0x27|批注开关|0x00 开 0x01关|
|0x28|退出移动授课||
附:按下/释放<a name="pointmove"></a>
| 名称 | 定义 | 具体内容 |
| --------- | ----------------- | --------------------------------------------------------------------------------------------- |
| EventType | 批注事件类型 | 0x01:`ACTION_DOWN`, 0x02:`ACTION_POINTER_DOWN`, 0x03:`ACTION_POINTER_UP`, 0x04:`ACTION_UP` |
| OpType | 操作类型 | 笔:0x01<br>橡皮擦:0x02 |
| TouchId | 当前事件的touchId | Int值(4个Byte) |
| x | 事件的x轴坐标点 | Int值(4个Byte) |
| y | 事件的y轴坐标点 | Int值(4个Byte) |
附:移动<a name="multipoint"></a>
| 名称 | 定义 | 具体内容 |
| ---------- | -------- | ----------------------------------------------------------------------- |
| OpType | 操作类型 | 笔:0x01<br>橡皮擦:0x02 |
| PointCount | 点个数 | 1byte |
| MovePoints | 移动的点 | 每个点有事件id(4byte),x坐标(4byte),y坐标(4byte),每多1个点就增加12个字节 |
##### 1.4.7.2.2. PPT操作
1. ANDROID
| 名称 | 定义 | 具体内容 |
| ---- | ---------------------- | --------------------------------------------------------------- |
| 0x50 | 请求演示ppt | |
| 0x51 | 翻页(下一页可能为动画) | 上一页:0x01<br>下一页:0x02<br>跳转:0x03+页码(byte) |
| 0x52 | 切换批注笔类型 | 0x01:普通笔 0x02:荧光笔 0x03:激光笔 0xff:普通指针 |
| 0x53 | 切换普通笔颜色 | 颜色值int(00 BB GG RR) |
| 0x54 | 批注事件发送 | 事件类型(down:0x01,move:0x02,up:0x03),事件坐标点(xy各4个Byte) |
| 0x55 | 退出演示 | |
2. PC
| 名称 | 定义 | 具体内容 |
| ---- | ----------------------- | -------------------------------------------------- |
| 0x5D | pc端退出演示 | |
| 0x5E | 当前有ppt启动,允许演示 | ip(string)+port(string)用于android连接下载预览图片 |
| 0x5F | 当没有ppt启动,拒绝演示 | |
#### 1.4.7.3. 小工具
1. ANDROID
| 代码 | 定义 |具体内容|
| ---- | ---- | ------ |
| 0x30 | 录屏操作 | 打开:0x01<br>停止:0xff<br>开始:0x02<br>暂停:0x03|
| 0x31 | 计时器 | 打开:0x01<br>关闭:0xff<br>开始:0x10<br>计时/倒计时 切换:0x20<br>计次:0x11<br>暂停:0x02<br>重置:0x03<br>设置倒计时时间:0x21+时(byte)+分(byte)+秒(byte)<br>全屏/非全屏: 0x30|
| 0x32 | 骰子 | 打开:0x01<br>关闭:0xff<br>生成:0x02<br>设置数量:0x10+数量(byte)|
| 0x33 | 聚光灯 | 打开:0x01<br>关闭:0xff<br>移动:0x10+dx,dy(各4个Byte)<br>放大:0x20+ds(4byte) 缩小时为负值|
| 0x34 | 抢答 | 打开:0x01<br>关闭:0xff<br>开始抢答:0x10|
| 0x35 | 随机挑人 | 打开:0x01<br>关闭:0xff<br>开始:0x02<br>设置人数:0x10+人数(byte)|
| 0x36 | 弹幕 | 打开:0x01<br>关闭:0xff<br>开始:0x02<br>暂停:0x03|
| 0x37 | 投票 | 进入投票:0x00+0xff<br>进入类型:0x00+题型<br>打开:0x01+题型+参数<br>题型:<br>- 书写(0x00)<br>- ABC选择(0x01)<br>- 123选择(0x02)<br>- 文字(0x03)<br>- 判断(0x04)<br>- 打分(0x05))<br>参数:<br>打分选项(byte)(0x01:5分,0x02:10分)<br>选择(选项数(byte)+单/多选(byte 0x01单 0x02多))))<br>停止:0xf0<br>设置: 0xfe+题型+参数<br>关闭题型:0xff+0x00<br>关闭投票:0xff+0xff |
|0x38|发送屏幕|发送:0x01|
|0x39|获取学生屏幕|打开:0x01<br>关闭:0xff<br>刷新:0x02|
|0x3A|发送文件给学生|通过鸿软传完的含后缀的文件名|
|0x3f|打开其它工具|类型(byte)+指令(byte)<br>类型:<br>- 小白板:0x01<br>- 实物展台:0x02<br>- 比分牌:0x03<br>- 时钟:0x04<br>- 节日:0x05<br>- 记忆卡片:0x06<br>- 拼图:0x07<br>- 日历:0x08<br>- 遮幕:0x09<br>- 元素周期表:0x0a<br>- 电子琴:0x0b<br>- 键盘:0x0c<br>指令<br>-打开0x01<br>-关闭:0xff|
|0x90|状态请求|0x00:互动课堂是否在上课<br>0x01:请求所有课堂<br>0x02:白板,0x00当前页码|
|0x91|上/下课|上课:0x00+课堂名称<br>下课:0x01|
1. PC
- 常规回应
| 代码 | 定义 | 具体内容 |
| ---- | -------- | -------------------------------------------------------- |
| 0x32 | 骰子 | 返回结果:数量(byte)+第1个点数(byte)+第2个点数(byte)+... |
| 0x34 | 抢答 | 抢答成功:学生姓名? |
| 0x35 | 随机挑人 | 返回结果:<br>0x00+学生数量(int)<br>0x01+数量(int)+第1个学生名+`"\"`+第二个学生名+... |
| 0x36 | 弹幕 | 返回弹幕:名字长度(int)+名字+内容 |
|0x37|投票|返回:总数(int)+已投数(int)|
|0x90|状态/错误回应|0x00互动课堂:0x01在上课,0x02不在上课,0x03课堂列表+课堂总数(int)+第一课堂名长(int)+第一课堂名(string)+...<br>0x02白板:0x00+当前页码(int)|
|0x91|上下课同步|0x00上课,0x01下课|
- 主动回应(pc端作相应的操作时同步给安卓)
回应码: **0xff**
| 代码 | 定义 |具体内容|
| ---- | ---- | ------ |
| 0x30 | 录屏操作 | 打开:0x01<br>停止:0xff<br>开始:0x02<br>暂停:0x03|
| 0x31 | 计时器 | 打开:0x01<br>关闭:0xff<br>开始:0x10<br>计时/倒计时 切换:0x20<br>计次:0x11<br>暂停:0x02<br>重置:0x03<br>设置倒计时时间:0x21+时(byte)+分(byte)+秒(byte)<br>全屏/非全屏: 0x30|
| 0x32 | 骰子 | 打开:0x01<br>关闭:0xff<br>生成:0x02<br>设置数量:0x10+数量(byte)|
| 0x33 | 聚光灯 | 打开:0x01<br>关闭:0xff<br>移动:0x10+dx,dy(各4个Byte)<br>放大:0x20+ds(4byte) 缩小时为负值|
| 0x34 | 抢答 | 打开:0x01<br>关闭:0xff<br>开始抢答:0x10|
| 0x35 | 随机挑人 | 打开:0x01<br>关闭:0xff<br>开始:0x02<br>设置人数:0x10+人数(byte)|
| 0x36 | 弹幕 | 打开:0x01<br>关闭:0xff<br>开始:0x02<br>暂停:0x03|
| 0x37 | 投票 | 进入投票:0x00+0xff<br>进入类型:0x00+题型<br>打开:0x01+题型+参数<br>题型:<br>- 书写(0x00)<br>- ABC选择(0x01)<br>- 123选择(0x02)<br>- 文字(0x03)<br>- 判断(0x04)<br>- 打分(0x05))<br>参数:<br>打分选项(byte)(0x01:5分,0x02:10分)<br>选择(选项数(byte)+单/多选(byte 0x01单 0x02多))))<br>停止:0xf0<br>设置: 0xfe+题型+参数<br>关闭题型:0xff+0x00<br>关闭投票:0xff+0xff|
|0x38|发送屏幕|发送:0x01|
|0x3f|打开其它工具|类型(byte)+指令(byte)<br>类型:<br>- 小白板:0x01<br>- 实物展台:0x02<br>- 比分牌:0x03<br>- 时钟:0x04<br>- 节日:0x05<br>- 记忆卡片:0x06<br>- 拼图:0x07<br>- 日历:0x08<br>- 遮幕:0x09<br>- 元素周期表:0x0a<br>- 电子琴:0x0b<br>- 键盘:0x0c<br>指令<br>-打开0x01<br>-关闭:0xff|
画布操作同步:有页面操作时重新请求预览图
| 名称 | 定义 | 具体内容 |
| ---- | ------------------------ | ----------------------------------------------------- |
| 0x2f | 翻页 | 上一页:0x01<br>下一页:0x02<br>跳转:0x03+页码(byte) |
| 0x21 | 切换笔类型 | 0x01:普通笔<br>0x02:激光笔<br>0x03:橡皮擦 |
| 0x22 | 切换普通笔颜色 | 0x01蓝色<br>0x02黄色<br>0x03红色<br>0x04黑色<br>0x05白色 |
| 0x23 | 修改普通笔宽度 | 0x01小<br>0x02中<br>0x03大 |
| 0x24 | 鼠标/触屏事件(按下/释放) | 见[按下/释下](#pointmove) |
| 0x25 | 单/多点移动事件(移动) | 见[移动](#multipoint) |
|0x26|页面操作|0x01:新建页,0x02:删除页,0x03:清空页,0x10:撤消,0x11:恢复,0x20:保存|
|0x27|批注开关|0x00 开 0x01关|
|0x28|退出移动授课||
#### AI助手
1. Android
| 代码 | 定义 | 具体内容 |
| ---- | --------------- | -------------------------------------------- |
| 0x60 | 启动/关闭AI助手 | 0x00启动,0x01关闭 |
| 0x61 | 流程 | 0x00:开始识别,0x01:识别成功,0x02:识别失败 |
| 0x62 | 指令说明 | 说明(string) |
2. PC
| 代码 | 定义 | 具体内容 |
| ---- | --------------- | ------------------ |
| 0x60 | 启动/关闭AI助手 | 0x00启动,0x01关闭 |
#### 云服务( 0x10 - 0x1F )
1. Android
| 代码 | 定义 | 具体内容 |
| ---- | --------------- | ------------------ |
| 0x10 | 登录同步 | 0x00 -> 安卓已登录同步到PC, 帐号字节长度(int),帐号(string);token字节长度(int),密码(string) |
#### 1.4.7.4. 移动授课
1. Android
| 代码 | 定义 | 具体内容 |
| ---- | --------------- | -------------------------------------------- |
| 0x40 | 开始授课 | 课件id长度(int)+ 课件id(string) |
| 0x41 | 保存课件 | 0x00不保存,0x01保存 |
| 0x42 | 取消下载 | |
| 0x43 | 退出云课件移动授课 | |
2. PC
| 代码 | 定义 | 具体内容 |
| ---- | --------------- | ------------------ |
| 0x40 | 当前课件状态 | 0x00课件下载中</br>0x01下载完成开始授课</br>0x02下载失败</br>0x03 未同步课件</br>0x04开始授课时存在打开课件</br>0xff关闭当前课件|
| 0x41 | tcp断开 |0x00 网络中断,0x01 退出账号 |
| 0x43 | 退出云课件移动授课 | |
#### 1.4.7.5. 文件胶囊
附:文件类型<a name="type1"></a>
| 代码 | 定义 |
| ---- | --------------- |
|0x00|PPT|
|0x01|EXCEL|
|0x02|WORD|
|0x03|图片|
|0x04|音频|
|0x05|视频|
|0x06|TXT|
|0x07|FLASH|
|0x08|IWB|
|0x09|PDF|
|0x0A|UBC|
|0x0B|UBM|
|0x0C|压缩包|
|0xFF|未知|
附:文件操作类型<a name="type2"></a>
| 代码 | 定义 |
| ---- | --------------- |
|0x00|打开|
|0x01|关闭|
|0x02|删除|
|0x03|新增|
|0x04|下载|
|0x05|下载缩略图(图片类型专用)|
1. Android
| 代码 | 定义 | 具体内容 |
| ---- | --------------- | -------------------------------------------- |
| 0x80 | 文件操作 | [文件操作类型(byte)](#type2) + 文件数量(int)+ (文件名称长度(int)+文件名称包含后缀名(string)+... ) |
| 0x81 | 清空文件胶囊 | |
| 0x82 | 获取文件胶囊列表 | |
2. PC
| 代码 | 定义 | 具体内容 |
| ---- | --------------- | ------------------ |
| 0x80 | 文件操作 | [文件操作类型(byte)](#type2) + 文件数量(int)+ (文件名称长度(int)+文件名称包含后缀名(string)+...) |
| 0x81 | 清空文件胶囊 | |
| 0x82 | 文件胶囊列表 |文件数量(int)+ (文件名称长度(int)+文件名称包含后缀名(string)+... ) |
```txt
#### 1.4.6.4. 图片旋转缩放事件
| 名称 | 定义 | 具体内容 |
| ---- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| 0x4C | 图片缩放事件 | 缩放比例float(4个Byte) 缩放中心点x坐标与view的中心点x坐标偏差值float(4个Byte) 缩放中心点y坐标与view的中心点y坐标偏差值float(4个Byte) |
| 0x4D | 图片位移 | x轴上的偏差值float(4个Byte) y轴上的偏差值float(4个Byte) |
| 0x4E | 图片旋转 | 旋转角度float(4个Byte) 旋转中心点为图片的中心点 |
| 0x4F | 重置图片旋转与缩放 | |
### 1.4.7. 图片浏览器退出,切换页指令
| 名称 | 定义 | 具体内容 |
| ---- | -------------- | ---------------------------------------- |
| 0x61 | 关闭图片浏览器 | |
| 0x62 | 切换图片 | 目标图片在图片列表中的index(int 4个Byte) |
### 1.4.8 基本信息帧
| 名称 | 定义 | 具体内容 |
| ---- | ------------------ | ------------------------------------- |
| 0x00 | PC/ANDROID基本信息 | 0x01+设备名+"$"+分辨率高+"$"+分辨率宽 |
### 1.4.8. PC传屏android的操作事件定义
| 名称 | 定义 | 具体内容 |
| ---- | -------- | ------------------------------------------------------------ |
| 0x70 | 按钮点击 | 左键(0x01)或中键(0x02)或右键(0x03)+down(0x01)或release(0x02) |
| 0x71 | 指针移动 | 指针x轴偏移量dx(4个Byte)+指针y轴偏移量dy(4个Byte) |
```