李勇

1.修改会议状态的pdu结构,增加开始上课、暂停、关闭会议的接口

此 diff 太大无法显示。
... ... @@ -97,8 +97,9 @@ export default class MessageEntrance extends Emiter {
this.leaveClass=this._leaveClass;
this.getMcuClientStatus=this._getMcuClientStatus;
this.getClassDetail=this._getClassDetail;
this.sendUpdaterClassInfo=this._sendUpdaterClassInfo;
this.sendStartClass=this._sendStartClass;
this.sendPauseClass=this._sendPauseClass;
this.sendCloseClass=this._sendCloseClass;
//chatApe
this.sendChatMsg=this._sendChatMsg;
... ... @@ -432,19 +433,25 @@ export default class MessageEntrance extends Emiter {
};
this._emit(msg.type, msg);
}
//更新会议数据
_sendUpdaterClassInfo(_param){
//开始上课
_sendStartClass(_param){
if(_confer_ape){
_confer_ape.sendUpdaterClassInfo(_param);
_confer_ape.startClass(_param);
}
}
_sendUpdaterClassStatus(_param){
//暂停上课
_sendPauseClass(_param){
if(_confer_ape){
_confer_ape.sendUpdaterClassStatus(_param);
_confer_ape.pauseClass(_param);
}
}
//停止上课
_sendCloseClass(_param){
if(_confer_ape){
_confer_ape.closeClass(_param);
}
}
//ChatApe
... ...
... ... @@ -26,11 +26,22 @@ class EngineUtils{
return null;
}
//生成时间戳 保证唯一
//生成时间戳后9位 保证唯一
static creatTimestamp(){
let time = new Date().getTime();
let timestamp:int = time % 1000000000;//time后9位
return timestamp;
}
//生成时间戳 string
static creatTimestampStr(){
let curTime = new Date();
let timeStr = "" + curTime.getFullYear() + "-";
timeStr += (curTime.getMonth()+1) + "-";
timeStr += curTime.getDate() + "-";
timeStr+=curTime.getHours() + "-";
timeStr+=curTime.getMinutes() + "-";
timeStr+=curTime.getSeconds();
return timeStr;
}
}
export default EngineUtils;
\ No newline at end of file
... ...
... ... @@ -5,6 +5,7 @@ import Loger from 'Loger';
import ApeConsts from "apes/ApeConsts";
let loger = Loger.getLoger('GlobalConfig');
import EngineUtils from 'EngineUtils';
class GlobalConfig {
constructor () {
... ... @@ -112,17 +113,19 @@ class GlobalConfig {
"classStatus":this.classStatus,//课堂的状态
"classStartTime":this.classStartTime,//课堂点击开始时间
"classStopTime":this.classStopTime,//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
"classTimestamp":this.recordTimestamp,//相对于点开始课堂的时间戳
"classTimestamp":this.classTimestamp,//相对于点开始课堂的时间戳
"classBeginTime":this.classBeginTime,//课堂创建的时间
"classEndTime":this.classEndTime,//课堂结束的时间
"classBeginTime":this.classBeginTime,//课堂创建的时间,这个是Sass返回的
"classEndTime":this.classEndTime,//课堂结束的时间,这个是Sass返回的
"recordStatus":this.recordStatus,//当前录制状态
"recordTimestamp":this.recordTimestamp,//相对于开始录制的时间戳
"recordStreamName":this.recordStreamName,//录制的文件名
"recordTimestamp":this.recordTimestamp,//相对于首次开始录制的时间戳
"recordFileName":this.recordFileName,//录制的文件名
"recordDownloadUrl":this.recordDownloadUrl,//下载地址
"systemTimestamp":this.systemTimestamp//当前的系统时间戳
"serverTimestamp":this.serverTimestamp,//当前的系统时间戳
"activeDocId":this.activeDocId ,//当前激活的文档ID
"activeDocCurPage":this.activeDocCurPage//当前激活的文档的当前页
}
}
}
... ... @@ -170,6 +173,9 @@ class GlobalConfig {
return false;
}
static get serverTimestamp(){
return EngineUtils.creatTimestamp();
}
//储存已经提前上传的文档列表
static setDocListPrepare(_data){
if(_data==null) return;
... ... @@ -261,43 +267,46 @@ GlobalConfig.maxAudioChannels=1;
GlobalConfig.maxMediaChannels=2;
GlobalConfig.isDebug=false;
GlobalConfig.deBugData={};
GlobalConfig.deviceType=-1; //设备类型 0:电脑 1:安卓 2:ios -1未知
GlobalConfig.userIP="";//用户当前IP
GlobalConfig.userId=0;
GlobalConfig.userName="";
GlobalConfig.nodeId=0;//随机生成
GlobalConfig.nodeId=0;//随机生成 mcu中的唯一ID
GlobalConfig.passwordRequired=false;
GlobalConfig.password="";
GlobalConfig.userType=8;
GlobalConfig.userRole=ApeConsts.normal;//用户的身份,5种类型:
GlobalConfig.role=ApeConsts.NR_NORMAL;//课堂角色身份
GlobalConfig.h5Module=0;
GlobalConfig.siteId="gust";
GlobalConfig.h5Module=1;//是否支持H5
GlobalConfig.topNodeID=101;//现在固定值,还不知道是做什么用
GlobalConfig.siteId="gust";//站点号
GlobalConfig.className= ""; // 课程名称
GlobalConfig.classId=0;//课堂号=classId=meetingNumber 之后统一修改为classId
GlobalConfig.classType=ApeConsts.CLASS_TYPE_INTERACT;//1:互动课堂,2:直播课堂
GlobalConfig.classType=ApeConsts.CLASS_TYPE_INTERACT;//课堂类型 1:互动课堂,2:直播课堂
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_WAIT;// 0;//课堂还未开始 1;//直播中 2 //课间休息 3已经停止
GlobalConfig.classStartTime="";//课堂点击开始时间
GlobalConfig.classStopTime="";//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
GlobalConfig.classBeginTime="";//课堂创建的时间,这个是Sass返回的
GlobalConfig.classEndTime="";//课堂结束的时间,这个是Sass返回的
GlobalConfig.classTimestamp=0;//从课堂开始到现在的时
GlobalConfig.recordStatus=false;//当前录制状态
GlobalConfig.recordTimestamp=0;//相对于首次开始录制的进行时间
GlobalConfig.recordFileName="";//录制的文件名
GlobalConfig.recordDownloadUrl="";//下载地址
GlobalConfig.recordReplaytickValues={}; // 滚动条关键点,用于快进快退
//GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get set 获取
GlobalConfig.classBeginTime="";//课堂创建的时间
GlobalConfig.classEndTime="";//课堂结束的时间
GlobalConfig.recordStartTime= "";
GlobalConfig.recordStartTimestam = "";
GlobalConfig.recordEndTimestamp = "";
GlobalConfig.recordTimestamp= "";
GlobalConfig.activeDocId=0;//当前激活的文档ID
GlobalConfig.activeDocCurPage=1;//当前激活的文档的当前页
GlobalConfig.recordEndTime= "";
GlobalConfig.recordPlayURL= "";
GlobalConfig.recordConfigFile = ""; // 录制脚本文件
GlobalConfig.tickValues={}; // 滚动条关键点,用于快进快退
... ...
... ... @@ -11,11 +11,13 @@ ApeConsts.CLASS_STATUS_WAIT= 0;//课堂还未开始
ApeConsts.CLASS_STATUS_STARTED= 1;//直播中
ApeConsts.CLASS_STATUS_PAUSE= 2;//暂停
ApeConsts.CLASS_STATUS_CLOSE= 3;//结束
ApeConsts.CLASS_STATUS_UPTATE= 4;//更新课堂状态信息
ApeConsts.CLASS_WAIT_START = "class.wait.start";//课堂还未开始
ApeConsts.CLASS_STARTING = "class.started";//直播中
ApeConsts.CLASS_PAUSING = "class.pause";//暂停
ApeConsts.CLASS_PAUSING = "class.closed";//关闭
ApeConsts.CLASS_PAUSING = "class.update";//更新当前的状态信息
//课堂类型
ApeConsts.CLASS_TYPE_INTERACT= 1; // 互动课堂,通过MS转发音视频,不能进行H5观看
... ...
... ... @@ -22,9 +22,15 @@ import UTF8 from 'utf-8';
import Loger from 'Loger';
import GlobalConfig from 'GlobalConfig';
import EngineUtils from 'EngineUtils';
let loger = Loger.getLoger('ConferApe');
let itemIdx=0;//table插入新数据的计数id,目前用时间戳
let timerCounter;
const ACTION_TYPE_0=0;
const ACTION_TYPE_1=1;
const ACTION_TYPE_2=2;
const ACTION_TYPE_3=3;
const ACTION_TYPE_4=4;
class ConferApe extends Ape {
constructor() {
super(
... ... @@ -44,8 +50,8 @@ class ConferApe extends Ape {
// 默认值: normal
this.hostUserId = '';//主持人的 第三方userId
this.rosters = {};//用户列表
this.activeDocId =0;//当前激活的文档ID
this.activeDocCurPage=1;//当前激活的文档的当前页
//this.activeDocId =0;//当前激活的文档ID
//this.activeDocCurPage=1;//当前激活的文档的当前页
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
... ... @@ -137,21 +143,48 @@ class ConferApe extends Ape {
this.sendUniform(adapterPdu, true);
}
//开始上课
startClass(_param){
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_STARTED;
GlobalConfig.classStartTime=EngineUtils.creatTimestampStr();
_param.actionType=ACTION_TYPE_1;
this.sendUpdaterClassStatusInfo(_param);
}
//暂停上课
pauseClass(_param){
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_PAUSE;
GlobalConfig.classStopTime=EngineUtils.creatTimestampStr();
_param.actionType=ACTION_TYPE_2;
this.sendUpdaterClassStatusInfo(_param);
}
//关闭课堂
closeClass(_param){
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_CLOSE;
GlobalConfig.classStopTime=EngineUtils.creatTimestampStr();
_param.actionType=ACTION_TYPE_3;
this.sendUpdaterClassStatusInfo(_param);
}
//更新课堂状态
updateClassStatus(_param){
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_UPTATE;
_param.actionType=ACTION_TYPE_4;
this.sendUpdaterClassStatusInfo(_param);
}
//更新会议信息
sendUpdaterClassInfo(_param){
loger.log('sendUpdaterClassInfo----------');
sendUpdaterClassStatusInfo(_param){
loger.log('sendUpdaterClassStatusInfo----------');
if(_param==null||EngineUtils.isEmptyObject(_param)){
loger.log('sendUpdaterClassInfo,参数错误');
loger.log('sendUpdaterClassStatusInfo,参数错误');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return ;
}
itemIdx=_param.itemIdx;
let whiteBoardModelPdu = this.packPdu(_param,itemIdx);
console.log(whiteBoardModelPdu);
itemIdx=ApeConsts.CONFERENCE_OBJ_TABLE_ID;// itemIdx=_param.itemIdx;
let modelPdu = this.packPdu(_param,itemIdx);
//console.log(modelPdu);
if(whiteBoardModelPdu==null){
loger.log('sendUpdaterClassInfo,参数错误');
if(modelPdu==null){
loger.log('sendUpdaterClassStatusInfo,参数错误');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return ;
}
... ... @@ -160,21 +193,21 @@ class ConferApe extends Ape {
tableItemPdu.itemIdx=itemIdx;
tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定
tableItemPdu.registerObjId=ApeConsts.CONFERENCE_OBJ_TABLE_ID;
tableItemPdu.itemData =whiteBoardModelPdu.toArrayBuffer();
tableItemPdu.itemData =modelPdu.toArrayBuffer();
//updater
let whiteBoardUpdateItem = new pdu['RCRegistryTableUpdateItemPdu'];
let tableUpdateItem = new pdu['RCRegistryTableUpdateItemPdu'];
//optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
//repeated RCRegistryTableItemPdu items = 2;
whiteBoardUpdateItem.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
whiteBoardUpdateItem.items.push(tableItemPdu);
tableUpdateItem.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
tableUpdateItem.items.push(tableItemPdu);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_TABLE_ID;
updateObjPdu.subType = whiteBoardUpdateItem.type;
updateObjPdu.userData = whiteBoardUpdateItem.toArrayBuffer();
updateObjPdu.subType = tableUpdateItem.type;
updateObjPdu.userData = tableUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
... ... @@ -189,20 +222,20 @@ class ConferApe extends Ape {
this.sendUniform(adapterPdu,true);
}
//更新会议状态
/* //更新会议状态
sendUpdaterClassStatus(_param){
loger.log('sendUpdaterClassStatus----------');
if(_param==null||EngineUtils.isEmptyObject(_param)){
loger.log('sendUpdaterClassInfo,参数错误');
loger.log('sendUpdaterClassStatusInfo,参数错误');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return ;
}
itemIdx=_param.itemIdx;
let whiteBoardModelPdu = this.packPdu(_param,itemIdx);
console.log(whiteBoardModelPdu);
let modelPdu = this.packPdu(_param,itemIdx);
console.log(modelPdu);
if(whiteBoardModelPdu==null){
loger.log('sendUpdaterClassInfo,参数错误');
if(modelPdu==null){
loger.log('sendUpdaterClassStatusInfo,参数错误');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return ;
}
... ... @@ -211,21 +244,21 @@ class ConferApe extends Ape {
tableItemPdu.itemIdx=itemIdx;
tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定
tableItemPdu.registerObjId=ApeConsts.CONFERENCE_OBJ_TABLE_ID;
tableItemPdu.itemData =whiteBoardModelPdu.toArrayBuffer();
tableItemPdu.itemData =modelPdu.toArrayBuffer();
//updater
let whiteBoardUpdateItem = new pdu['RCRegistryTableUpdateItemPdu'];
let tableUpdateItem = new pdu['RCRegistryTableUpdateItemPdu'];
//optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
//repeated RCRegistryTableItemPdu items = 2;
whiteBoardUpdateItem.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
whiteBoardUpdateItem.items.push(tableItemPdu);
tableUpdateItem.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
tableUpdateItem.items.push(tableItemPdu);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_TABLE_ID;
updateObjPdu.subType = whiteBoardUpdateItem.type;
updateObjPdu.userData = whiteBoardUpdateItem.toArrayBuffer();
updateObjPdu.subType = tableUpdateItem.type;
updateObjPdu.userData = tableUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
... ... @@ -238,7 +271,7 @@ class ConferApe extends Ape {
console.log("会议发送更新数据111============");
this.sendUniform(adapterPdu,true);
}
}*/
///////白板数据的封包和解包/////////////////////////////////////////
packPdu(_param,_itemIdx){
... ... @@ -249,19 +282,64 @@ class ConferApe extends Ape {
return null;
}
/* message RCClassStatusInfoPdu {
optional uint32 node_id=1;//mcu中的唯一ID
optional uint32 user_id=2;
optional uint32 user_name=3;
optional uint32 site_id=4;//站点号
optional uint32 class_id=5;
optional uint32 class_name=6;
required uint32 class_type=7;//课堂类型
required uint32 class_status=9;//课堂的状态
optional uint32 class_startTime=10;//课堂点击开始时间
optional uint32 class_stopTime=11;//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
optional uint32 class_timestamp=12;//相对于点开始课堂的时间戳
optional uint32 class_beginTime=13;//课堂创建的时间,这个是Sass返回的
optional uint32 class_endTime=14;//课堂结束的时间,这个是Sass返回的
optional uint32 record_status=15;//当前录制状态
optional uint32 record_timestamp=16;//相对于首次开始录制的时间戳
optional uint32 record_fileName=17;//录制的文件名
optional uint32 record_downloadUrl=18;//下载地址
optional uint32 server_timestamp=19;//当前的系统时间戳
}*/
let classStatusInfo=new pdu['RCClassStatusInfoPdu'];
classStatusInfo.nodeId=GlobalConfig.nodeId;//mcu中的唯一ID
classStatusInfo.userId=GlobalConfig.userId;
classStatusInfo.userName=GlobalConfig.userName;
classStatusInfo.siteId=GlobalConfig.siteId;//站点号
classStatusInfo.classId=GlobalConfig.classId;
classStatusInfo.className=GlobalConfig.className;
classStatusInfo.classType=GlobalConfig.classType;//课堂类型
classStatusInfo.classStatus=GlobalConfig.classStatus;//课堂的状态
classStatusInfo.classStartTime=GlobalConfig.classStartTime;//课堂点击开始时间
classStatusInfo.classStopTime=GlobalConfig.classStopTime;//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
classStatusInfo.classTimestamp=GlobalConfig.classTimestamp;//相对于点开始课堂的时间戳
classStatusInfo.classBeginTime=GlobalConfig.classBeginTime;//课堂创建的时间,这个是Sass返回的
classStatusInfo.classEndTime=GlobalConfig.classEndTime;//课堂结束的时间,这个是Sass返回的
classStatusInfo.recordStatus=GlobalConfig.recordStatus;//当前录制状态
classStatusInfo.recordTimestamp=GlobalConfig.recordTimestamp;//相对于首次开始录制的时间戳
classStatusInfo.recordFileName=GlobalConfig.recordFileName;//录制的文件名
classStatusInfo.recordDownloadUrl=GlobalConfig.recordDownloadUrl;//下载地址
classStatusInfo.serverTimestamp=GlobalConfig.serverTimestamp;//当前的系统时间戳
classStatusInfo.activeDocId=GlobalConfig.activeDocId;//当前激活的文档id
classStatusInfo.activeDocCurPage=GlobalConfig.activeDocCurPage;//当前激活的文档的当前页
/*
optional uint32 class_status= 1;//当前课堂状态 //0:未开始,1,开始,2,暂停
optional string class_timestamp= 2;//目前用这个变量来记录时间 flash用的这个
optional item_idx=3;
optional from=4;
optional uint32 item_idx=1;
optional uint32 from=2;
optional uint32 owner=3;
optional uint32 action_type=4;//状态改变的类型
optional RCClassStatusInfoPdu class_status_info=5;//当前课堂状态的信息
*/
//判断type类型,根据type设置不同的参数
let modelPdu =new pdu['RCClassSendDataModelPdu'];
modelPdu.itemIdx=_itemIdx;
modelPdu.owner=GlobalConfig.nodeId;
modelPdu.from=GlobalConfig.nodeId;
modelPdu.classStatus =2;
modelPdu.classTimestamp=32532532;
modelPdu.owner=GlobalConfig.nodeId;
modelPdu.actionType =_param.actionType;
modelPdu.classStatusInfo=classStatusInfo;
console.log(modelPdu);
return modelPdu;
... ... @@ -275,8 +353,8 @@ class ConferApe extends Ape {
}
try{
let docModelPdu= pdu['RCClassSendDataModelPdu'].decode(itemData);
return docModelPdu;
let modelPdu= pdu['RCClassSendDataModelPdu'].decode(itemData);
return modelPdu;
}catch (err){
loger.log("会议收到数据 unPackPdu Pdu解析错误,itemIdx="+itemIdx+" err:"+err.message);
}
... ...
... ... @@ -23,6 +23,7 @@ import EngineUtils from 'EngineUtils';
let loger = Loger.getLoger('DocApe');
let itemIdx=0;//table插入新数据的计数id,目前用时间戳
class DocApe extends Ape {
constructor() {
super(
... ... @@ -31,16 +32,17 @@ class DocApe extends Ape {
ApeConsts.DOCSHARING_SESSION_TAG
);
this.docList = {};//记录文档的数组this.docList[itemIdx]=itemIdx的数据
this.activeDocItemIdx =0;//当前激活的文档itemIdx
this.activeDocCurPage=1;//当前激活的文档的当前页
// 延迟
this._apeDelayed = true;
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.DOCSHARING_OBJ_TABLE_ID, ApeConsts.DOCSHARING_OBJ_TABLE_NAME, ApeConsts.DOCSHARING_OBJ_TABLE_TAG, 0, new ArrayBuffer);
//this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.DOCSHARING_OBJ_TABLE_ID_H5, ApeConsts.DOCSHARING_OBJ_TABLE_NAME_H5, ApeConsts.DOCSHARING_OBJ_TABLE_TAG_H5, 0, new ArrayBuffer);
// 延迟
this._apeDelayed = true;
}
/////////////发送数据操作//////////////////////////////////////////////////////
//上传文档
documentUpload(paramInfo){
... ... @@ -282,6 +284,7 @@ class DocApe extends Ape {
let itemDataInfo = this.unPackPdu(owner, itemIdx, itemData);
this.docList[itemIdx] = itemDataInfo;
loger.log('tableInsertHandler',itemDataInfo);
this._emit(MessageTypes.DOC_UPLOAD,itemDataInfo);
}
tableDeleteHandler(object_id, tableDeleteData){
... ... @@ -296,6 +299,7 @@ class DocApe extends Ape {
for (let i=0;i<len;i++){
if(this.docList[itemIdxs[i]]){
loger.log("删除文档数据:",itemIdxs[i]);
this._emit(MessageTypes.DOC_DELETE,itemIdxs[i]);
delete this.docList[itemIdxs[i]];
}
}
... ... @@ -307,6 +311,7 @@ class DocApe extends Ape {
if(itemDataInfo!=null){
this.docList[itemIdx] = itemDataInfo;
loger.log('tableUpdateHandler',itemDataInfo);
this._emit(MessageTypes.DOC_UPDATE,itemDataInfo);
}else {
loger.log('tableUpdateHandler 数据无效--> itemIdx',itemIdx);
}
... ...
... ... @@ -864,10 +864,33 @@ message RCWhiteBoardDataModel {
optional bytes data = 13;//暂时预留的参数
}
message RCClassSendDataModelPdu {
optional uint32 class_status= 1;//当前课堂状态 //0:未开始,1,开始,2,暂停
optional uint32 class_timestamp= 2;//目前用这个变量来记录时间 flash用的这个
optional uint32 item_idx=3;
optional uint32 from=4;
optional uint32 item_idx=1;
optional uint32 from=2;
optional uint32 owner=3;
optional uint32 action_type=4;//状态改变的类型
optional RCClassStatusInfoPdu class_status_info=5;//当前课堂状态的信息
}
message RCClassStatusInfoPdu {
optional uint32 node_id=1;//mcu中的唯一ID
optional string user_id=2;
optional string user_name=3;
optional string site_id=4;//站点号
optional uint32 class_id=5;
optional string class_name=6;
required uint32 class_type=7;//课堂类型
required uint32 class_status=9;//课堂的状态
optional string class_startTime=10;//课堂点击开始时间
optional string class_stopTime=11;//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
optional uint32 class_timestamp=12;//相对于点开始课堂的时间戳
optional string class_beginTime=13;//课堂创建的时间,这个是Sass返回的
optional string class_endTime=14;//课堂结束的时间,这个是Sass返回的
optional bool record_status=15;//当前录制状态
optional uint32 record_timestamp=16;//相对于首次开始录制的时间戳
optional string record_fileName=17;//录制的文件名
optional string record_downloadUrl=18;//下载地址
optional uint32 server_timestamp=19;//当前的系统时间戳
optional uint32 active_doc_id=20;//当前激活的文档id
optional uint32 active_doc_cur_page=21;//当前激活的文档的当前页
}
//end
... ...