李勇

增加用户身份处理,同一个课堂只能有一个主持人,一个助教,一个主讲人,一个监课,如果新进入的用户是这几个身份,会踢掉当前课堂内同样身份的人

... ... @@ -90,6 +90,7 @@ class EverSocket extends Emiter {
return;
}
this._setConnected(false);//先设置状态
this._enableEverSocket = false;
this.websocket.onopen = undefined;
this.websocket.onclose = undefined;
this.websocket.onerror = undefined;
... ... @@ -100,7 +101,7 @@ class EverSocket extends Emiter {
loger.log('ignore errors');
}
this.websocket = undefined;
this._enableEverSocket = false;
}
_onOpen() {
... ...
... ... @@ -92,7 +92,7 @@ MessageTypes.ERR_CLASS_JOIN_FULL=204;//人数已满
MessageTypes.ERR_CLASS_MD5_WRONG=205;//MD5验证失败
MessageTypes.ERR_CLASS_PASSWORD_WRONG=206;//密码错误
MessageTypes.ERR_CLASS_JOIN_CONFILICT=207;//已经在其它地方登陆
MessageTypes.ERR_CLASS_KICK_OUT=208;//有相同身份的人员加入课堂,自己被踢出;
MessageTypes.ERR_GET_CLASS_DETAIL=300;//获取classDetail失败
MessageTypes.ERR_GET_CLASS_PARAML=301;//获取ClassParam失败
... ... @@ -137,6 +137,7 @@ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FULL]="人数已满";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_MD5_WRONG]="MD5验证失败";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_PASSWORD_WRONG]="密码错误";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_CONFILICT]="已经在其它地方登陆";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_KICK_OUT]="有相同身份的人员加入课堂,自己被踢出课堂";
MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_DETAIL]="获取classDetail失败";
... ...
... ... @@ -35,7 +35,7 @@ public static const NR_GUEST:uint = 0; // 客人
public static const NR_NORMAL:uint = 1; // 普通与会者
public static const NR_ADMIN:uint = 2; // 管理员
public static const NR_MASTER:uint = 4; // 主持人
public static const NR_SLAVE:uint = 8; // 主讲人
public static const NR_PRESENTER:uint = 8; // 主讲人
public static const NR_ASSISTANT:uint = 16; // 助教
public static const NR_INVISIBLE:uint = 32; // 隐身用户
*/
... ... @@ -45,8 +45,8 @@ public static const NR_INVISIBLE:uint = 32; // 隐身用户
//ApeConsts.NR_GUEST = 0; // 客人
ApeConsts.NR_NORMAL = 1;// 普通与会者
ApeConsts.NR_ADMIN = 2;// 管理员
ApeConsts.NR_MASTER = 4; // 主持人
ApeConsts.NR_SLAVE = 8; // 主讲人
ApeConsts.NR_HOST = 4; // 主持人
ApeConsts.NR_PRESENTER = 8; // 主讲人
ApeConsts.NR_ASSISTANT = 16; // 助教
ApeConsts.NR_INVISIBLE = 32; // 隐身用户
... ... @@ -58,6 +58,23 @@ ApeConsts.normal="normal";//(普通角色/学生)
ApeConsts.record="record";//(暂时没用.
ApeConsts.invisible="invisible";//隐身用户
//下面做身份的数字和字符串对应关系
ApeConsts.userTypes={};
ApeConsts.userTypes[ApeConsts.NR_NORMAL]=ApeConsts.normal;
ApeConsts.userTypes[ApeConsts.NR_ADMIN]=ApeConsts.record;
ApeConsts.userTypes[ApeConsts.NR_HOST]=ApeConsts.host;
ApeConsts.userTypes[ApeConsts.NR_PRESENTER]=ApeConsts.presenter;
ApeConsts.userTypes[ApeConsts.NR_ASSISTANT]=ApeConsts.assistant;
ApeConsts.userTypes[ApeConsts.NR_INVISIBLE]=ApeConsts.invisible;
ApeConsts.userTypesToId={};
ApeConsts.userTypesToId[ApeConsts.normal]=ApeConsts.NR_NORMAL;
ApeConsts.userTypesToId[ApeConsts.record]=ApeConsts.NR_ADMIN;
ApeConsts.userTypesToId[ApeConsts.host]=ApeConsts.NR_HOST;
ApeConsts.userTypesToId[ApeConsts.presenter]=ApeConsts.NR_PRESENTER;
ApeConsts.userTypesToId[ApeConsts.assistant]=ApeConsts.NR_ASSISTANT;
ApeConsts.userTypesToId[ApeConsts.invisible]=ApeConsts.NR_INVISIBLE;
////最新定义的角色身份 20170220
//ApeConsts.USER_TYPE_HOST=1;//(主持人/老师)
//ApeConsts.USER_TYPE_ASSISTANT=2;//(助教)
... ...
... ... @@ -162,7 +162,12 @@ class AudioApe extends Ape {
}
//释放nodeId占用的所有频道
_releaseNodeIdAllChannel(nodeId){
loger.log(nodeId,"_releaseNodeIdAllChannel");
loger.log(nodeId,"_releaseNodeIdAllChannel",this.mcu.connected);
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
if (openingChannel == 0) {
loger.warn(nodeId,"没有占用channel不需要处理");
... ...
... ... @@ -14,624 +14,651 @@ import EngineUtils from 'EngineUtils';
import TimerCounter from "TimerCounter";
let loger = Loger.getLoger('ConferApe');
let itemIdx=0;//table插入新数据的计数id,目前用时间戳
let itemIdx = 0;//table插入新数据的计数id,目前用时间戳
class ConferApe extends Ape {
constructor() {
super(
ApeConsts.CONFERENCE_SESSION_ID,
ApeConsts.CONFERENCE_SESSION_NAME,
ApeConsts.CONFERENCE_SESSION_TAG
);
// Attribures
this.hostNodeId = -1;//主持人的nodeId
// 用户的身份,5种类型:
// host(主持人/老师)
// presenter(主讲人)
// assistant(助教)
// normal(普通角色/学生)
// record(暂时没用.
// 默认值: normal
this.hostUserId = '';//主持人的 第三方userId
this.rosters = {};//用户列表
this.timerCounter=new TimerCounter();//计时器
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_ROSTER, ApeConsts.CONFERENCE_OBJ_ROSTER_ID,
ApeConsts.CONFERENCE_OBJ_ROSTER_NAME, ApeConsts.CONFERENCE_OBJ_ROSTER_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_QUEUE, ApeConsts.CONFERENCE_OBJ_QUEUE_ID,
ApeConsts.CONFERENCE_OBJ_QUEUE_NAME, ApeConsts.CONFERENCE_OBJ_QUEUE_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.CONFERENCE_OBJ_TABLE_ID,
ApeConsts.CONFERENCE_OBJ_TABLE_NAME, ApeConsts.CONFERENCE_OBJ_TABLE_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_COUNTER, ApeConsts.CONFERENCE_OBJ_COUNTER_ID,
ApeConsts.CONFERENCE_OBJ_COUNTER_NAME, ApeConsts.CONFERENCE_OBJ_COUNTER_TAG, 0, new ArrayBuffer);
this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
this.on(pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST, this.conferMsgComingHandler.bind(this));//这个是会议消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
this.on(pdu.RCPDU_CONFERENCE_RECORD_REQUEST,this.onSendConferRecordRequestHandler.bind(this));//发送录制和停止录制消息
}
//加入会议
_joinSessionHandler(_data) {
let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
loger.log("_joinSessionHandler nodeInfoRecordPdu=");
console.log(nodeInfoRecordPdu);
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType =GlobalConfig.deviceType;//设备类型
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let rosterUpdateItem = new pdu['RCRegistryRosterUpdateItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_UPDATE_PDU;
rosterUpdateItem.items.push(item);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
sendConferMsg(_messageInfo) {
if(this._classInfo==null||EngineUtils.isEmptyObject(this._classInfo)){
loger.log('不能发送会议消息.McuClient还未初始化数据!');
if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
return ;
constructor() {
super(
ApeConsts.CONFERENCE_SESSION_ID,
ApeConsts.CONFERENCE_SESSION_NAME,
ApeConsts.CONFERENCE_SESSION_TAG
);
/*
// Attribures
this.hostNodeId = -1;//主持人的nodeId
// 用户的身份,5种类型:
// host(主持人/老师)
// presenter(主讲人)
// assistant(助教)
// normal(普通角色/学生)
// record(暂时没用.
// 默认值: normal
this.hostUserId = '';//主持人的 第三方userId
*/
this.rosters = {};//用户列表
this.timerCounter = new TimerCounter();//计时器
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_ROSTER, ApeConsts.CONFERENCE_OBJ_ROSTER_ID,
ApeConsts.CONFERENCE_OBJ_ROSTER_NAME, ApeConsts.CONFERENCE_OBJ_ROSTER_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_QUEUE, ApeConsts.CONFERENCE_OBJ_QUEUE_ID,
ApeConsts.CONFERENCE_OBJ_QUEUE_NAME, ApeConsts.CONFERENCE_OBJ_QUEUE_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.CONFERENCE_OBJ_TABLE_ID,
ApeConsts.CONFERENCE_OBJ_TABLE_NAME, ApeConsts.CONFERENCE_OBJ_TABLE_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_COUNTER, ApeConsts.CONFERENCE_OBJ_COUNTER_ID,
ApeConsts.CONFERENCE_OBJ_COUNTER_NAME, ApeConsts.CONFERENCE_OBJ_COUNTER_TAG, 0, new ArrayBuffer);
this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
this.on(pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST, this.conferMsgComingHandler.bind(this));//这个是会议消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
this.on(pdu.RCPDU_CONFERENCE_RECORD_REQUEST, this.onSendConferRecordRequestHandler.bind(this));//发送录制和停止录制消息
}
// to, message
loger.log('发送会议消息.', _messageInfo);
/* message RCConferenceSendDataRequestPdu {
optional uint32 initiator = 1;
optional uint32 peer = 2;
required bool is_public = 3;
required bytes user_data = 4;
}
*/
let conferSendPdu = new pdu['RCConferenceSendDataRequestPdu'];
conferSendPdu.type = pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST;
conferSendPdu.initiator = this._classInfo.nodeId;//发起人
conferSendPdu.peer = parseInt(_messageInfo.to);//发送给谁,公聊的时候是0,私聊的时候是指定的用户id
conferSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message);
//conferSendPdu.userData =UTF8.setBytesFromString(_messageInfo.message);
conferSendPdu.isPublic = true;
conferSendPdu.actionType=_messageInfo.actionType;
// if (!(conferSendPdu.isPublic || 0 === conferSendPdu.peer)) {
if (!conferSendPdu.isPublic && 0!=conferSendPdu.peer) {
//发送给制定的人
loger.log('发送私聊会议消息.');
this.send(conferSendPdu);
} else {
//发送给所有人
loger.log('发送公聊会议消息.');
this.sendChatUniform(conferSendPdu);
//加入会议
_joinSessionHandler(_data) {
let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
loger.log("_joinSessionHandler nodeInfoRecordPdu=");
console.log(nodeInfoRecordPdu);
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType;//设备类型
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let rosterUpdateItem = new pdu['RCRegistryRosterUpdateItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_UPDATE_PDU;
rosterUpdateItem.items.push(item);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
}
//发送录制或停止录制的消息,{"recordStatus":true};true为开始录制,false为停止录制
sendConferRecordMsg(_param) {
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
sendConferMsg(_messageInfo) {
if (this._classInfo == null || EngineUtils.isEmptyObject(this._classInfo)) {
loger.log('不能发送会议消息.McuClient还未初始化数据!');
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
return;
}
// to, message
loger.log('发送会议消息.', _messageInfo);
/* message RCConferenceSendDataRequestPdu {
optional uint32 initiator = 1;
optional uint32 peer = 2;
required bool is_public = 3;
required bytes user_data = 4;
}
*/
let conferSendPdu = new pdu['RCConferenceSendDataRequestPdu'];
conferSendPdu.type = pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST;
conferSendPdu.initiator = this._classInfo.nodeId;//发起人
conferSendPdu.peer = parseInt(_messageInfo.to);//发送给谁,公聊的时候是0,私聊的时候是指定的用户id
conferSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message);
//conferSendPdu.userData =UTF8.setBytesFromString(_messageInfo.message);
conferSendPdu.isPublic = true;
conferSendPdu.actionType = _messageInfo.actionType;
// if (!(conferSendPdu.isPublic || 0 === conferSendPdu.peer)) {
if (!conferSendPdu.isPublic && 0 != conferSendPdu.peer) {
//发送给制定的人
loger.log('发送私聊会议消息.');
this.send(conferSendPdu);
} else {
//发送给所有人
loger.log('发送公聊会议消息.');
this.sendChatUniform(conferSendPdu);
}
}
// to, message
loger.log('发送录制消息.', _param);
if(_param==null){
loger.warn("控制录制状的消息发送失败,参数错误",_param);
return;
//发送录制或停止录制的消息,{"recordStatus":true};true为开始录制,false为停止录制
sendConferRecordMsg(_param) {
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
// to, message
loger.log('发送录制消息.', _param);
if (_param == null) {
loger.warn("控制录制状的消息发送失败,参数错误", _param);
return;
}
/* message RCConferenceRecordRequestPdu {
optional uint32 initiator = 1; // 发起录像指令的node id
optional bool record = 2; // 录像指令 true:开始录像, false:停止录像
optional uint32 class_time = 3; // 课堂进行时间(秒)
optional string filename = 4; // 录像文件名称,filename中增加目录部分
}*/
//保存当前的录制状态
GlobalConfig.recordStatus = _param.recordStatus || false;
let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu'];
conferRecordSendPdu.type = pdu.RCPDU_CONFERENCE_RECORD_REQUEST;
conferRecordSendPdu.peer = 0;//channel 为0
conferRecordSendPdu.isPublic = true;
conferRecordSendPdu.initiator = this._classInfo.nodeId;//发起人
conferRecordSendPdu.record = GlobalConfig.recordStatus;
conferRecordSendPdu.classTime = GlobalConfig.classTimestamp;
conferRecordSendPdu.filename = GlobalConfig.recordFileName || GlobalConfig.classId + "_" + EngineUtils.creatTimestampYMD() + ".rec";
this.sendChatUniform(conferRecordSendPdu);
}
/* message RCConferenceRecordRequestPdu {
optional uint32 initiator = 1; // 发起录像指令的node id
optional bool record = 2; // 录像指令 true:开始录像, false:停止录像
optional uint32 class_time = 3; // 课堂进行时间(秒)
optional string filename = 4; // 录像文件名称,filename中增加目录部分
}*/
//保存当前的录制状态
GlobalConfig.recordStatus=_param.recordStatus||false;
let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu'];
conferRecordSendPdu.type = pdu.RCPDU_CONFERENCE_RECORD_REQUEST;
conferRecordSendPdu.peer = 0;//channel 为0
conferRecordSendPdu.isPublic = true;
conferRecordSendPdu.initiator = this._classInfo.nodeId;//发起人
conferRecordSendPdu.record =GlobalConfig.recordStatus;
conferRecordSendPdu.classTime=GlobalConfig.classTimestamp;
conferRecordSendPdu.filename=GlobalConfig.recordFileName||GlobalConfig.classId+"_"+EngineUtils.creatTimestampYMD()+".rec";
this.sendChatUniform(conferRecordSendPdu);
}
//开启录制
startRecord(){
loger.log('startRecord',"isHost",GlobalConfig.isHost,"recordStatus",GlobalConfig.recordStatus);
//如果是host
if(GlobalConfig.isHost){
GlobalConfig.classStopTime=EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({"recordStatus":true});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this._emit(MessageTypes.CLASS_RECORD_START);//会议开始录制
//开启录制
startRecord() {
loger.log('startRecord', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
//如果是host
if (GlobalConfig.isHost) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({"recordStatus": true});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this._emit(MessageTypes.CLASS_RECORD_START);//会议开始录制
}
}
}
//停止录制
stopRecord(){
loger.log('stopRecord',"isHost",GlobalConfig.isHost,"recordStatus",GlobalConfig.recordStatus);
//如果是host,并且当前正在录制中
if(GlobalConfig.isHost&&GlobalConfig.recordStatus){
GlobalConfig.classStopTime=EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({"recordStatus":false});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//停止录制
stopRecord() {
loger.log('stopRecord', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
//如果是host,并且当前正在录制中
if (GlobalConfig.isHost && GlobalConfig.recordStatus) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({"recordStatus": false});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
}
}
}
//主动离开会议,发送通知到服务器
leaveClass(){
let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType;
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let rosterUpdateItem = new pdu['RCRegistryRosterDeleteItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_DELETE_PDU;
rosterUpdateItem.nodeId=GlobalConfig.nodeId;
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
//还原课堂状态
restorClass(){
GlobalConfig.classTimestamp=0;
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_WAIT;
GlobalConfig.classStopTime=EngineUtils.creatTimestampStr();
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this.sendUpdaterClassStatusInfo({"actionType":0});
loger.log('restorClass');
}
//开始上课
startClass(_param){
if(GlobalConfig.isHost){
let timestamp=EngineUtils.creatTimestampStr();
GlobalConfig.classStopTime=timestamp;
//如果录制的文件名不存在,需要创建一个名字
let timestampYMD=EngineUtils.creatTimestampYMD();
GlobalConfig.recordFileName=GlobalConfig.recordFileName||
GlobalConfig.siteId+"/"+timestampYMD+"/"
+GlobalConfig.classId+"_"+timestampYMD+".rec";//4、文件名称 $RECORD_HOME/`site id`/`日期`/`filename` 例:/data/record/su/20161216/`filename`
if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_WAIT){
//之前是为开始状态,第一次点开始
GlobalConfig.classStartTime=timestamp;
}
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_STARTED;
//开始录制
this.startRecord();
//会议状态改变
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步会议状态
this.sendUpdaterClassStatusInfo({"actionType":1});
//开始计时
this.startTimerCounter();
}else {
loger.warn('没有权限');
//主动离开会议,发送通知到服务器
leaveClass() {
let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType;
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let rosterUpdateItem = new pdu['RCRegistryRosterDeleteItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_DELETE_PDU;
rosterUpdateItem.nodeId = GlobalConfig.nodeId;
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
}
//暂停上课
pauseClass(_param){
if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_WAIT){
loger.warn('还没有开始,不能点暂停');
return;
//还原课堂状态
restorClass() {
GlobalConfig.classTimestamp = 0;
GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_WAIT;
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this.sendUpdaterClassStatusInfo({"actionType": 0});
loger.log('restorClass');
}
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_PAUSE;
GlobalConfig.classStopTime=EngineUtils.creatTimestampStr();
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this.sendUpdaterClassStatusInfo({"actionType":2});
this.stopTimerCounter();
}
//关闭课堂
closeClass(_param){
if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_WAIT){
loger.warn('还没有开始,不能点关闭');
return;
//开始上课
startClass(_param) {
if (GlobalConfig.isHost) {
let timestamp = EngineUtils.creatTimestampStr();
GlobalConfig.classStopTime = timestamp;
//如果录制的文件名不存在,需要创建一个名字
let timestampYMD = EngineUtils.creatTimestampYMD();
GlobalConfig.recordFileName = GlobalConfig.recordFileName ||
GlobalConfig.siteId + "/" + timestampYMD + "/"
+ GlobalConfig.classId + "_" + timestampYMD + ".rec";//4、文件名称 $RECORD_HOME/`site id`/`日期`/`filename` 例:/data/record/su/20161216/`filename`
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
//之前是为开始状态,第一次点开始
GlobalConfig.classStartTime = timestamp;
}
GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_STARTED;
//开始录制
this.startRecord();
//会议状态改变
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步会议状态
this.sendUpdaterClassStatusInfo({"actionType": 1});
//开始计时
this.startTimerCounter();
} else {
loger.warn('没有权限');
}
}
this.stopTimerCounter();
this.restorClass();
//把所有人都踢出课堂
this.sendConferMsg({"to":0,"message":"所有人退出会议","actionType":ApeConsts.CLASS_ACTION_CLOSE_ALL});
}
//暂停上课
pauseClass(_param) {
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
loger.warn('还没有开始,不能点暂停');
return;
}
GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_PAUSE;
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
//更新会议信息
sendUpdaterClassStatusInfo(_param){
loger.log('sendUpdaterClassStatusInfo');
if(_param==null||EngineUtils.isEmptyObject(_param)){
loger.log('sendUpdaterClassStatusInfo,参数错误');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return ;
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this.sendUpdaterClassStatusInfo({"actionType": 2});
this.stopTimerCounter();
}
itemIdx=ApeConsts.CONFERENCE_OBJ_TABLE_ID;// itemIdx=_param.itemIdx;
let modelPdu = this.packPdu(_param,itemIdx);
//loger.log('sendUpdaterClassStatusInfo----2------');
console.log(modelPdu);
if(modelPdu==null){
loger.log('sendUpdaterClassStatusInfo,参数错误');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return ;
//关闭课堂
closeClass(_param) {
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
loger.warn('还没有开始,不能点关闭');
return;
}
this.stopTimerCounter();
this.restorClass();
//把所有人都踢出课堂
this.sendConferMsg({"to": 0, "message": "所有人退出会议", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL});
}
let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
tableItemPdu.itemIdx=itemIdx;
tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定
tableItemPdu.registerObjId=ApeConsts.CONFERENCE_OBJ_TABLE_ID;
tableItemPdu.itemData =modelPdu.toArrayBuffer();
//更新会议信息
sendUpdaterClassStatusInfo(_param) {
loger.log('sendUpdaterClassStatusInfo');
if (_param == null || EngineUtils.isEmptyObject(_param)) {
loger.log('sendUpdaterClassStatusInfo,参数错误');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return;
}
itemIdx = ApeConsts.CONFERENCE_OBJ_TABLE_ID;// itemIdx=_param.itemIdx;
let modelPdu = this.packPdu(_param, itemIdx);
//loger.log('sendUpdaterClassStatusInfo----2------');
console.log(modelPdu);
if (modelPdu == null) {
loger.log('sendUpdaterClassStatusInfo,参数错误');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return;
}
let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
tableItemPdu.itemIdx = itemIdx;
tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定
tableItemPdu.registerObjId = ApeConsts.CONFERENCE_OBJ_TABLE_ID;
tableItemPdu.itemData = modelPdu.toArrayBuffer();
//updater
let tableUpdateItem = new pdu['RCRegistryTableUpdateItemPdu'];
//optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
//repeated RCRegistryTableItemPdu items = 2;
tableUpdateItem.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
tableUpdateItem.items.push(tableItemPdu);
//updater
let tableUpdateItem = new pdu['RCRegistryTableUpdateItemPdu'];
//optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
//repeated RCRegistryTableItemPdu items = 2;
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 = tableUpdateItem.type;
updateObjPdu.userData = tableUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_TABLE_ID;
updateObjPdu.subType = tableUpdateItem.type;
updateObjPdu.userData = tableUpdateItem.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
console.log("会议发送更新数据============");
this.sendUniform(adapterPdu,true);
}
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
console.log("会议发送更新数据============");
this.sendUniform(adapterPdu, true);
}
/////收到消息处理/////////////////////////////////////////////////////////////////////////////////
//加入channel成功
onJoinChannelHandlerSuccess(){
loger.log('ConferApe.onJoinChannelHandlerSuccess',GlobalConfig.classStatus);
this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this),1);
//如果当前会议正在进行中,开启计时器
if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_STARTED){
//开始计时
this.startTimerCounter();
/////收到消息处理/////////////////////////////////////////////////////////////////////////////////
//加入channel成功
onJoinChannelHandlerSuccess() {
loger.log('ConferApe.onJoinChannelHandlerSuccess', GlobalConfig.classStatus);
this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1);
//如果当前会议正在进行中,开启计时器
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
//开始计时
this.startTimerCounter();
//如果是host ,开始录制
this.startRecord();
//如果是host ,开始录制
this.startRecord();
}
}
}
//开启计时器
startTimerCounter(){
this.timerCounter.startTimer();
}
//停止计时器
stopTimerCounter(){
this.timerCounter.stopTimer();
}
timerCounterUptate(){
if(!this.mcu.connected){
loger.warn('MCU 连接已经断开');
this.stopTimerCounter();
//开启计时器
startTimerCounter() {
this.timerCounter.startTimer();
}
//如果还没开始或已经暂停、关闭,不做计时处理
if(GlobalConfig.classStatus!=ApeConsts.CLASS_STATUS_STARTED){
loger.warn('当前课堂已经暂停或者未开始,不计时',"classStatus-->",GlobalConfig.classStatus);
return;
//停止计时器
stopTimerCounter() {
this.timerCounter.stopTimer();
}
GlobalConfig.classTimestamp=GlobalConfig.classTimestamp+1;//计时
//loger.log('课堂进行时间',GlobalConfig.classTimestamp);
this._emit(MessageTypes.CLASS_UPDATE_TIMER,{"classTimestamp":GlobalConfig.classTimestamp});
if(GlobalConfig.classTimestamp%GlobalConfig.updateClassInfoDelay==0){
//如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
if(GlobalConfig.isHost){
//保存数据到Sass
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步消息给其他人
this.sendUpdaterClassStatusInfo({"actionType":1});
timerCounterUptate() {
if (!this.mcu.connected) {
loger.warn('MCU 连接已经断开');
this.stopTimerCounter();
}
//如果还没开始或已经暂停、关闭,不做计时处理
if (GlobalConfig.classStatus != ApeConsts.CLASS_STATUS_STARTED) {
loger.warn('当前课堂已经暂停或者未开始,不计时', "classStatus-->", GlobalConfig.classStatus);
return;
}
GlobalConfig.classTimestamp = GlobalConfig.classTimestamp + 1;//计时
//loger.log('课堂进行时间',GlobalConfig.classTimestamp);
this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": GlobalConfig.classTimestamp});
if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
//如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
if (GlobalConfig.isHost) {
//保存数据到Sass
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步消息给其他人
this.sendUpdaterClassStatusInfo({"actionType": 1});
}
}
}
}
tableUpdateHandler(owner, itemIdx, itemData) {
try {
let model=this.unPackPdu(owner, itemIdx,itemData);
loger.log('tableUpdateHandler');
console.log(model);
//处理会议更新的信息
if(model&&model.classStatusInfo){
GlobalConfig.setClassStatusInfo(model.classStatusInfo);
}
//通知应用层更新会议状态
this._emit(MessageTypes.CLASS_UPTATE_STATUS,GlobalConfig.classStatusInfo);
//如果MCU已经断开连接,停止计时器
if(!this.mcu.connected){
//停止计时
this.stopTimerCounter();
return;
}
if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_STARTED){
//如果会议在进行中,开始计时器
this.startTimerCounter();
}else {
//停止计时
this.stopTimerCounter();
}
} catch (e) {
loger.warn('ConferApe table update got exception. itemIdx',itemIdx);
}
}
conferMsgComingHandler(_data) {
//flash RCConferenceSendDataRequestPdu
//loger.warn('conferMsgComingHandler needs to be handled.');
//const recordInfo = pdu['RCWhiteboardDataRequestPdu'].decode(pdu);
//loger.log("conferMsgComingHandler",recordInfo);
var chatReceivePdu = pdu['RCConferenceSendDataRequestPdu'].decode(_data);
var chatMsg = {};
chatMsg.fromNodeID = chatReceivePdu.initiator;
chatMsg.toNodeID = chatReceivePdu.peer;
chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
chatMsg.actionType=chatReceivePdu.actionType;
loger.log("conferMsgComingHandler",chatMsg);
switch (chatMsg.actionType){
case ApeConsts.CLASS_ACTION_CLOSE_ALL:
loger.log(chatMsg.message);
//会议关闭,所有人都退出
this._emit(MessageTypes.CLASS_EXIT);
break;
default:
break;
}
}
onSendConferRecordRequestHandler(_data){
loger.log("onSendConferRecordRequestHandler");
try{
let conferRecordSendPdu =pdu['RCConferenceRecordRequestPdu'].decode(_data);
console.log(conferRecordSendPdu);
}catch (err){
loger.warn("onSendConferRecordRequestHandler err",err.message);
tableUpdateHandler(owner, itemIdx, itemData) {
try {
let model = this.unPackPdu(owner, itemIdx, itemData);
loger.log('tableUpdateHandler');
console.log(model);
//处理会议更新的信息
if (model && model.classStatusInfo) {
GlobalConfig.setClassStatusInfo(model.classStatusInfo);
}
//通知应用层更新会议状态
this._emit(MessageTypes.CLASS_UPTATE_STATUS, GlobalConfig.classStatusInfo);
//如果MCU已经断开连接,停止计时器
if (!this.mcu.connected) {
//停止计时
this.stopTimerCounter();
return;
}
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
//如果会议在进行中,开始计时器
this.startTimerCounter();
} else {
//停止计时
this.stopTimerCounter();
}
} catch (e) {
loger.warn('ConferApe table update got exception. itemIdx', itemIdx);
}
}
}
rosterInsertHandler(nodeId, nodeData) {
if(GlobalConfig.nodeId==nodeId){
loger.log("自己加入 rosterInsertHandler");
}else {
loger.log("有人加入 rosterInsertHandler");
this.rosterUpdateHandler(nodeId, nodeData);
}
}
//更新人员列表数据
rosterUpdateHandler(nodeId, nodeData) {
if (nodeData.role === ApeConsts.NR_MASTER ||
nodeData.role === ApeConsts.NR_SLAVE) {
this.hostNodeId = nodeData.nodeId;
this.hostUserId = nodeData.userId;
conferMsgComingHandler(_data) {
//flash RCConferenceSendDataRequestPdu
//loger.warn('conferMsgComingHandler needs to be handled.');
//const recordInfo = pdu['RCWhiteboardDataRequestPdu'].decode(pdu);
//loger.log("conferMsgComingHandler",recordInfo);
var chatReceivePdu = pdu['RCConferenceSendDataRequestPdu'].decode(_data);
var chatMsg = {};
chatMsg.fromNodeID = chatReceivePdu.initiator;
chatMsg.toNodeID = chatReceivePdu.peer;
chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
chatMsg.actionType = chatReceivePdu.actionType;
loger.log("conferMsgComingHandler", chatMsg);
switch (chatMsg.actionType) {
case ApeConsts.CLASS_ACTION_CLOSE_ALL:
loger.log(chatMsg.message);
//收到会议关闭,所有人都退出,执行自己关闭的流程
this._emit(MessageTypes.CLASS_EXIT);
break;
default:
break;
}
}
if (nodeData.role === ApeConsts.NR_NORMAL &&
this.hostNodeId === nodeData.nodeId) {
this.hostNodeId = -1;
this.hostUserId = '';
onSendConferRecordRequestHandler(_data) {
loger.log("onSendConferRecordRequestHandler");
try {
let conferRecordSendPdu = pdu['RCConferenceRecordRequestPdu'].decode(_data);
console.log(conferRecordSendPdu);
} catch (err) {
loger.warn("onSendConferRecordRequestHandler err", err.message);
}
}
//判断进入的用户身份,如果进入的人身份是host,助教,监课,并且和自己的身份冲突,自己会被踢掉
rosterInsertHandler(nodeId, nodeData) {
if (GlobalConfig.nodeId == nodeId) {
loger.log("自己加入 rosterInsertHandler");
} else {
loger.log("有人加入 rosterInsertHandler");
this.rosterUpdateHandler(nodeId, nodeData);
}
}
//更新人员列表数据
rosterUpdateHandler(nodeId, nodeData) {
//如果是自己的信息,不处理跳过
if (nodeId == GlobalConfig.nodeId) {
loger.log("自己加入课堂的消息,不需要处理");
this.rosters[nodeId] = nodeData;
return;
}
let rosterExists = this.rosters[nodeId];
this.rosters[nodeId] = nodeData;
let userDataObj=null;
if (!rosterExists) {
try{
userDataObj=pdu['RCNodeInfoUserDataPdu'].decode(nodeData.userData);
}catch (err){
loger.log("RCNodeInfoUserDataPdu decode err",err.message);
}
loger.log(nodeId, "加入课堂,role-->", nodeData.role, ApeConsts.userTypes[nodeData.role]);
//新加入的人员不是自己
//1.判断进入的用户身份,如果进入的人身份是host,助教,监课,并且和自己的身份冲突,自己会被踢掉
//2.最后进入的人会踢掉之前进入的人,nodeId是按时间戳生成的,最后进入的人nodeId的值比之前进入的人大
if (parseInt(nodeId) > GlobalConfig.nodeId) {
if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) {
this.kickOutRoster();
return;
} else if (nodeData.role == ApeConsts.NR_PRESENTER && GlobalConfig.isPresenter) {
this.kickOutRoster();
return;
} else if (nodeData.role == ApeConsts.NR_ASSISTANT && GlobalConfig.isAssistant) {
this.kickOutRoster();
return;
} else if (nodeData.role == ApeConsts.NR_INVISIBLE && GlobalConfig.isInvisible) {
this.kickOutRoster();
return;
}
}
let newNodeData=nodeData;
newNodeData.userData=userDataObj;
loger.log("更新人员列表数据 rosterUpdateHandler",{"nodeId":nodeId});
this._emit(MessageTypes.CLASS_INSERT_ROSTER, {"nodeId":nodeId,"nodeData":newNodeData});
this.emitRosterChange();
//处理用户信息
let rosterExists = this.rosters[nodeId];
this.rosters[nodeId] = nodeData;
let userDataObj = null;
if (!rosterExists) {
try {
userDataObj = pdu['RCNodeInfoUserDataPdu'].decode(nodeData.userData);
} catch (err) {
loger.log("RCNodeInfoUserDataPdu decode err", err.message);
}
let newNodeData = nodeData;
newNodeData.userData = userDataObj;
this._emit(MessageTypes.CLASS_INSERT_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData});
this.emitRosterChange();
} else {
//loger.log("更新人员列表数据,rosterExists已经存在",rosterExists);
}
}
}else {
//loger.log("更新人员列表数据,rosterExists已经存在",rosterExists);
//踢出用户
kickOutRoster() {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_KICK_OUT);
this._emit(MessageTypes.CLASS_EXIT);
}
}
//视频模块发生更新,人员状态需要更新
updaterRosterStatus(_param){
if(_param){
//loger.log("媒体模块发生更新,人员状态需要更新,fromNodeId->",_param.fromNodeId);
//loger.log(_param.status,_param.fromNodeId);
//console.log(_param.fromNodeId);
//如果是自己。改变自己的状态同步到MCU
//if(_param.fromNodeId==GlobalConfig.nodeId){
//
//}
//如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的
if(_param.status==ApeConsts.CHANNEL_STATUS_OPENING&&this.rosters[_param.fromNodeId]==null){
loger.log("媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->",_param);
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER,{"nodeId":_param.fromNodeId});
}
//视频模块发生更新,人员状态需要更新
updaterRosterStatus(_param) {
if (_param) {
//loger.log("媒体模块发生更新,人员状态需要更新,fromNodeId->",_param.fromNodeId);
//loger.log(_param.status,_param.fromNodeId);
//console.log(_param.fromNodeId);
//如果是自己。改变自己的状态同步到MCU
//if(_param.fromNodeId==GlobalConfig.nodeId){
//
//}
//如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的
if (_param.status == ApeConsts.CHANNEL_STATUS_OPENING && this.rosters[_param.fromNodeId] == null) {
loger.log("媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->", _param);
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": _param.fromNodeId});
}
}
}
}
//删除用户
rosterDelHandler(nodeId) {
if(GlobalConfig.nodeId==nodeId){
loger.log("自己离开 rosterDelHandler");
// 自己退出
this._emit(MessageTypes.CLASS_EXIT);
}else {
loger.log("有人离开 rosterDelHandler");
delete this.rosters[nodeId];
this.emitRosterChange();
this._emit(MessageTypes.CLASS_DELETE_ROSTER, {"nodeId":nodeId});
//当前人员列表中抽一个人来检查离开人员是否占用频道
for (let key in this.rosters){
let randNodeId=parseInt(key);
if(randNodeId==GlobalConfig.nodeId){
loger.log(randNodeId,"有权限检查离开的人员是否占用channel");
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId":nodeId});
}else {
loger.warn(GlobalConfig.nodeId,"没有权限检查离开的人员是否占用channel");
//删除用户
rosterDelHandler(nodeId) {
if (GlobalConfig.nodeId == nodeId) {
loger.log("自己离开课堂");
// 自己退出
this._emit(MessageTypes.CLASS_EXIT);
} else {
loger.log(nodeId, "离开课堂");
delete this.rosters[nodeId];
this.emitRosterChange();
this._emit(MessageTypes.CLASS_DELETE_ROSTER, {"nodeId": nodeId});
//当前人员列表中抽一个人来检查离开人员是否占用频道
for (let key in this.rosters) {
let randNodeId = parseInt(key);
if (randNodeId == GlobalConfig.nodeId) {
loger.log(randNodeId, "有权限检查离开的人员是否占用channel");
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": nodeId});
} else {
loger.warn(GlobalConfig.nodeId, "没有权限检查离开的人员是否占用channel");
}
return;
}
}
return;
}
}
}
//广播当前的人数
emitRosterChange() {
this._emit(MessageTypes.CLASS_UPDATE_ROSTER_NUM, Object.keys(this.rosters).length);
}
///////数据的封包和解包/////////////////////////////////////////
packPdu(_param,_itemIdx){
loger.log("会议===packPdu ");
//验证坐标点集合数组是否合法
if(_param==null||_itemIdx==null){
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
//广播当前的人数
emitRosterChange() {
this._emit(MessageTypes.CLASS_UPDATE_ROSTER_NUM, Object.keys(this.rosters).length);
}
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;//当前激活的文档的当前页
loger.log("classStatusInfo-------------",classStatusInfo);
/*
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.from=GlobalConfig.nodeId;
modelPdu.owner=GlobalConfig.nodeId;
//modelPdu.actionType =_param.actionType;
modelPdu.classStatusInfo=classStatusInfo;
return modelPdu;
}
unPackPdu(owner, itemIdx,itemData){
loger.log("会议===unPackPdu ");
if(owner==null||itemIdx==null||itemData==null){
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
///////数据的封包和解包/////////////////////////////////////////
packPdu(_param, _itemIdx) {
loger.log("会议===packPdu ");
//验证坐标点集合数组是否合法
if (_param == null || _itemIdx == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
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;//当前激活的文档的当前页
loger.log("classStatusInfo-------------", classStatusInfo);
/*
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.from = GlobalConfig.nodeId;
modelPdu.owner = GlobalConfig.nodeId;
//modelPdu.actionType =_param.actionType;
modelPdu.classStatusInfo = classStatusInfo;
return modelPdu;
}
try{
let modelPdu= pdu['RCClassSendDataModelPdu'].decode(itemData);
return modelPdu;
}catch (err){
loger.log("会议收到数据 unPackPdu Pdu解析错误,itemIdx="+itemIdx+" err:"+err.message);
unPackPdu(owner, itemIdx, itemData) {
loger.log("会议===unPackPdu ");
if (owner == null || itemIdx == null || itemData == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
try {
let modelPdu = pdu['RCClassSendDataModelPdu'].decode(itemData);
return modelPdu;
} catch (err) {
loger.log("会议收到数据 unPackPdu Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message);
}
return null;
}
return null;
}
}
... ...
... ... @@ -164,7 +164,12 @@ class VideoApe extends Ape {
}
//释放nodeId占用的所有频道
_releaseNodeIdAllChannel(nodeId){
loger.log(nodeId,"_releaseNodeIdAllChannel");
loger.log(nodeId,"_releaseNodeIdAllChannel",this.mcu.connected);
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
if (openingChannel == 0) {
loger.warn(nodeId,"没有占用channel不需要处理");
... ...
... ... @@ -181,7 +181,7 @@ class MCU extends Emiter {
nodeInfoRecordPdu.name = this.classInfo.userName;
nodeInfoRecordPdu.nodeId = this.classInfo.nodeId;
nodeInfoRecordPdu.userId = this.classInfo.userId;
nodeInfoRecordPdu.role = 1; //NR_NORMAL
nodeInfoRecordPdu.role = ApeConsts.userTypesToId[this.classInfo.userRole]||1; //NR_NORMAL用户的身份,根据用户登录时的身份设置
nodeInfoRecordPdu.level = 0;
let conferenceRecord = {}; //RCConferenceRecord_T
... ...