李勇
306bb164 1 parent 954e84d0 master ... 20170922-1 20171019-1 20171120-1w dev letv-20170426 ly20170622 ly20170622-2 ly20170622-3 ly20170627-2 ly20170706-1 ly20170708-2 ly20170708-3 ly20170710-1 ly20170717-1 ly20170719-1 ly20170723-1 ly20170724-2 ly20170726-1 ly20170731-1 ly20170731-2 ly20170801-2 ly20170802-1 ly20170818-1 ly20170818-2 ly20170820-1 ly20170821-1 ly20170824-1 ly20170829-1 ly20170925-1 ly20170926-1 ly20170927-1 ly20170929-1 ly20171011-1 ly20171013-1 ly20171013-2 ly20171016-1 ly20171021-1 ly20171023-1 ly20171024-1w ly20171025-1w ly20171026-1w ly20171027-1w ly20171030-1 ly20171030-2w ly20171107-1 ly20171110-1w ly20171113-1w ly20171204-1w ly20171208-1w ly20171211-1w ly20171211-2w ly20171214-1w mcuClientBranch mcuClientBranch20170228 webRtc-dev 1.7.0 v2.38.13.20171216 v2.38.11.20171214 v2.38.3.201712011 v2.38.1.201712011 v2.36.11.20171204 v2.36.8.20171206 v2.36.4.20171201 v2.35.11.20171130 v2.34.16.20171128 v2.34.5.20171127 v2.33.6.20171123 v2.32.1.20171123 v2.31.12.20171122 v2.31.10.20171122 v2.30.5.20171117 v2.30.2.20171117 v2.29.5.20171114 v2.28.1.20171110 v2.27.11.20171109 v2.26.9.20171107 v2.26.6.20171103 v2.26.2.20171102 v2.25.7.20171031 v2.25.6.20171031 v2.25.0.20171030 v2.24.2.20171030 v2.23.0.20171030 v2.22.7.20171026 v2.20.5.20171023 v2.20.0.20171021 v2.19.8.20171020 v2.18.14.20171020 v2.18.10.20171019 v2.17.11.20171014 v2.16.8.20171012 v2.16.5.20171012 v2.15.5.20171001 v2.15.3.20170929 v2.14.5.20170927 v2.13.5.20170927 v2.12.14.20170927 v2.12.8.20170926 v2.12.6.20170925 v2.11.13.20170925 v2.10.7.20170921 v2.10.6.20170921 v2.10.5.20170920 v2.10.4.20170920 v2.9.3.20170919 v2.8.17.20170918 v2.8.8.20170917 v2.8.2.20170916 v2.6.2.20170915 v2.5.12.20170915 v2.5.6.20170914 v2.5.5.20170914 v2.4.4.20170908 v2.4.2.20170908 v2.4.0.20170907 v2.3.6.20170907 v2.2.16.20170905 v2.1.22.20170904 v1.84.0.20170912 v1.83.2.20170831 v1.82.11.20170829 v1.81.19.20170828 v1.80.2.20170824 v1.79.6.20170822 v1.79.5.20170821 v1.79.4.20170821 v1.79.3.20170821 v1.78.4.20170820 v1.77.4.20170819 v1.76.2.20170818 v1.75.0.20170815 v1.74.0.20170814 v1.73.2.20170814 v1.73.1.20170814 v1.71.0.20170813 v1.70.5.20170812 v1.68.2.20170812 v1.66.1.20170809 v1.65.25.20170808 v1.65.24.20170806 v1.63.1.20170731 v1.62.3.20170731 v1.61.0.20170729 v1.60.0.20170729 v1.59.0.20170729 v1.58.0.20170729 v1.57.0.20170727 v1.56.1.20170727 v1.56.0.20170727 v1.52.1.20170726 v1.51.0.20170724 v1.50.7.20170724 v1.49.1.20170724 v1.48.2.20170723 v1.46.1.20170722 v1.45.1.20170717 v1.43.1.20170711 v1.42.1.20170708 v1.41.0.20170708 v1.40.0.20170706 v1.39.2.20170706 v1.39.1.20170705 v1.38.4.20170629 v1.37.5.20170627 v1.37.2.20170622 v1.36.7.20170620 v1.36.4.20170620 v1.36.1.20170619 v1.35.4.20170619 v1.34.2.20170615 v1.33.2.20170615 v1.32.1.20170614 v1.31.11.20170613 v1.30.20.20170607 v1.30.7.20170606 v1.30.6.20170606 v1.30.5.20170605 v1.30.3.20170602 v1.29.8.20170601 v1.28.0.201705031 v1.27.16.201705027 v1.27.14.201705027 v1.27.10.201705026 v1.25.2.201705025 v1.23.5.201705023 v1.23.4.201705018 v1.21.1.201705017 v1.20.1.201705015 v1.19.1.201705012 v1.19.0.201705011 v1.18.0.201705010 v1.16.1.201705010 v1.15.2.20170507 v1.14.1.20170505 v1.13.0.20170504 v1.11.3.20170504 v1.10.2.20170428 v1.10.0.20170427 v1.9.20.20170426 v1.9.19.20170425 v1.9.18.20170425 v1.9.17.20170421 v1.9.16.20170420 v1.9.15.20170420 v1.9.11.20170419 v1.9.6.20170418 v1.9.4.20170417 v.1.9.2.20170413 v.1.9.0.20170411 v.1.8.22.20170411 v.1.8.19.20170411 v.1.8.16.20170410 v.1.8.13.20170409 v.1.8.10.20170407 v.1.8.9.20170407 v1.8.8.20170406 v.1.8.7.20170405-1 v.1.8.6.20170401-2 v.1.8.5.20170331-1 v.1.8.3.20170329-4 v1.8.1.20170321 mcuClient20170302 mcuClient_v1.8.0.20170314 修复音视频channel占用问题

1.Sass增加保存开始录制信息的接口,储存录制文件名

2.增加录制的协议号和录制的pdu结构
3.会议模块增加开始录制和停止录制的接口
... ... @@ -65,6 +65,7 @@ export default class MessageEntrance extends Emiter {
_sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取会议的基本信息
_sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this));//获取会议的最全信息和历史保存的数据
_sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this));//保存会议状态信息
_sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this));//保存会议录制信息
_sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功
// 底层MCU消息层
... ... @@ -80,6 +81,7 @@ export default class MessageEntrance extends Emiter {
_confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this));//当前会议状态信息发生改变
_confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this));//当前会议人员离开
_confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER,this._onClassNonentityRoster.bind(this));//当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在
_confer_ape.on(MessageTypes.CLASS_RECORD_START,this._onClassRecordStart.bind(this));//会议开始录制
_chat_ape = new ChatApe();
... ... @@ -117,6 +119,7 @@ export default class MessageEntrance extends Emiter {
this.sendPauseClass = this._sendPauseClass;
this.sendCloseClass = this._sendCloseClass;
//chatApe
this.sendChatMsg = this._sendChatMsg;
... ... @@ -197,6 +200,18 @@ export default class MessageEntrance extends Emiter {
this._sassSaveClassStatusInfo();
}
//如果是第一次点击开始上课,需要创建录制时的文件名
_onClassRecordStart(_param){
if(GlobalConfig.getCurrentStatus().code!=GlobalConfig.statusCode_2.code){
loger.warn("不能保存会议状态",GlobalConfig.getCurrentStatus());
return;
}
if(_sass){
_sass.saveClassRecordContrlInfo(_param);
}
}
//有人员离开
_onClassDeleteRoster(_data){
//{"nodeId":nodeId}
... ... @@ -507,7 +522,7 @@ export default class MessageEntrance extends Emiter {
//根据从Sass获取的数据信息,同步最后一次保存的会议状态信息
loger.log("同步最后一次保存过的会议状态信息");
GlobalConfig.setClassStatusInfo(_data.currentInfo);
console.log(GlobalConfig.classStatusInfo)
console.log(GlobalConfig.classStatusInfo);
} else {
loger.log("还没有保存过会议状信息");
}
... ... @@ -535,6 +550,9 @@ export default class MessageEntrance extends Emiter {
_sassSaveClassStatusInfoSuccessHandler(_data) {
loger.log('保存会议状态信息成功.', _data);
}
_sassSaveClassRecordInfoSuccessHandler(_data){
loger.log('保存会议录制信息成功.', _data);
}
//Sass校验流程结束之后,开始加入MCU
_joinMCU() {
... ... @@ -671,6 +689,7 @@ export default class MessageEntrance extends Emiter {
}
//离开会议
if(_confer_ape){
_confer_ape.stopRecord();
_confer_ape.leaveClass();
}
//断开MCU连接
... ... @@ -680,6 +699,7 @@ export default class MessageEntrance extends Emiter {
}
}
//ChatApe
// 发送聊天消息
_sendChatMsg(_messageInfo) {
... ...
... ... @@ -52,6 +52,21 @@ class EngineUtils{
return timeStr;
}
//生成时间戳 格式:"20170209"
static creatTimestampYMD(){
let curTime = new Date();
let year = "" + curTime.getFullYear();
let month = "" +(curTime.getMonth()+1);
let day = "" + curTime.getDate();
if(month.length<2){
month="0"+month;
}
if(day.length<2){
day="0"+day;
}
return year+month+day;
}
static objectToBase64(_object){
try{
let _objectStr=JSON.stringify(_object);
... ...
... ... @@ -307,7 +307,7 @@ GlobalConfig.classTimestamp=0;//从课堂开始到现在的时
GlobalConfig.recordStatus=false;//当前录制状态
GlobalConfig.recordTimestamp=0;//相对于首次开始录制的进行时间
GlobalConfig.recordFileName="";//录制的文件名
GlobalConfig.recordFileName="";//录制的文件名,如 果为空就创建一个
GlobalConfig.recordDownloadUrl="";//下载地址
GlobalConfig.recordReplaytickValues={}; // 滚动条关键点,用于快进快退
... ...
... ... @@ -26,6 +26,7 @@ MessageTypes.CLASS_STATUS_INFO_CHANGE= 'class.status.info.change';//会议状态
MessageTypes.CLASS_UPDATE_TIMER='class.update.timer';//更新当前上课的时间
MessageTypes.CLASS_RECORD_START='class.record.start';//开始录制
... ...
... ... @@ -10,428 +10,436 @@ const loger = Loger.getLoger('Sass');
let confInfo = {};
class Sass extends Emiter {
constructor() {
super();
}
///////////////////////////////////////Sass 接口///////////////////////////////////////////////////
//Sass init初始化获取课堂校验信息-----------------------------------------------------------------
getJoinParams(_initInfo) {
/* 获取用于加入课堂的参数
/3m/api/meeting/joinParams.do
参数 (application/x-www-form-urlencoded):
名称 类型 可选 默认值 说明
meetingNumber String 否 null 课堂号
userID String 是 0 用户id
返回 (application/json):
code int 0 正常
1 课堂号必填
2 无效的课堂号
3 没有对应的站点
4 站点已过期
siteId String 站点号
passwordRequired Boolean 是否需要输入密码
md5 String 用于后续加入课堂验证
msType int 媒体服务器类型
classType 课堂类型
*/
let url = `http://${_initInfo.portal}/3m/api/meeting/joinParams.do?meetingNumber=${_initInfo.classId}&userID=${_initInfo.userId}`;
loger.log('1.初始化init获取课堂校验信息.');
console.log(url);
console.log(_initInfo);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`初始化init获取课堂校验信息-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_INIT_NETWORK);
throw '';
}
})
.then(ret => {
// code int 0 正常
// 1 课堂号必填
//2 无效的课堂号
//3 没有对应的站点
//4 站点已过期
if (ret.code === 0) {
loger.log('初始化init获取课堂校验信息-完成');
this._emit(Sass.CLASS_INIT_SUCCESS,ret);
} else if(ret.code === 1) {
//loger.warn('Sass获取课堂校验信息失败.');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_INIT_FAILED_1);
} else if(ret.code === 2) {
//loger.warn('Sass获取课堂校验信息失败.');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_INIT_FAILED_2);
} else if(ret.code === 3) {
//loger.warn('Sass获取课堂校验信息失败.');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_INIT_FAILED_3);
} else if(ret.code === 4) {
//loger.warn('Sass获取课堂校验信息失败.');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_INIT_FAILED_4);
}else {
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_INIT_FAILED,ret);
}
})
.catch(err => {
loger.error(`初始化init获取课堂校验信息-异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_INIT_PROTOCOL,err);
});
}
// Sass校验开始-->密码校验(如果需要密码)--->MD5校验----------------------------------------------------
passwordAndMd5Checking(_param) {
loger.log('2.开始Sass校验');
console.log(_param);
confInfo = _param;
// 密码校验
if (confInfo.passwordRequired === 'true'||confInfo.passwordRequired === true) {
this.sendPWDChecking();
return ;
constructor() {
super();
}
// MD5校验
this.sendMD5Checking();
}
// 入会密码校验---------------------------------------------------------------------------------------
sendPWDChecking() {
//let url = `http://${classInfo.portal}/3m/getCheckMeetinig.do?siteId=${classInfo.siteId}&classId=${classInfo.classId}&password=${classInfo.password}`;
/*
/3m/api/meeting/signIn.do
siteId 站点号
classId 课堂号(meetingNumber)
isTeacher 是否是老师:1 是 0 否
password 输入的密码
// 请求格式 http://112.126.80.182/3m/api/meeting/signIn.do?siteId=h5test&classId=526661904&password=111111&isTeacher=0
*/
//判断是否是老师
let isTeacher=0;
if(confInfo.userRole==ApeConsts.host){
isTeacher=1
///////////////////////////////////////Sass 接口///////////////////////////////////////////////////
//Sass init初始化获取课堂校验信息-----------------------------------------------------------------
getJoinParams(_initInfo) {
/* 获取用于加入课堂的参数
/3m/api/meeting/joinParams.do
参数 (application/x-www-form-urlencoded):
名称 类型 可选 默认值 说明
meetingNumber String 否 null 课堂号
userID String 是 0 用户id
返回 (application/json):
code int 0 正常
1 课堂号必填
2 无效的课堂号
3 没有对应的站点
4 站点已过期
siteId String 站点号
passwordRequired Boolean 是否需要输入密码
md5 String 用于后续加入课堂验证
msType int 媒体服务器类型
classType 课堂类型
*/
let url = `http://${_initInfo.portal}/3m/api/meeting/joinParams.do?meetingNumber=${_initInfo.classId}&userID=${_initInfo.userId}`;
loger.log('1.初始化init获取课堂校验信息.');
console.log(url);
console.log(_initInfo);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`初始化init获取课堂校验信息-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_NETWORK);
throw '';
}
})
.then(ret => {
// code int 0 正常
// 1 课堂号必填
//2 无效的课堂号
//3 没有对应的站点
//4 站点已过期
if (ret.code === 0) {
loger.log('初始化init获取课堂校验信息-完成');
this._emit(Sass.CLASS_INIT_SUCCESS, ret);
} else if (ret.code === 1) {
//loger.warn('Sass获取课堂校验信息失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_FAILED_1);
} else if (ret.code === 2) {
//loger.warn('Sass获取课堂校验信息失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_FAILED_2);
} else if (ret.code === 3) {
//loger.warn('Sass获取课堂校验信息失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_FAILED_3);
} else if (ret.code === 4) {
//loger.warn('Sass获取课堂校验信息失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_FAILED_4);
} else {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_FAILED, ret);
}
})
.catch(err => {
loger.error(`初始化init获取课堂校验信息-异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PROTOCOL, err);
});
}
let url = `http://${confInfo.portal}/3m/api/meeting/signIn.do?siteId=${confInfo.siteId}&classId=${confInfo.classId}&isTeacher=${isTeacher}&password=${confInfo.password}`;
loger.log('3.会议密码校验', url);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.status === 200) {
return ret.text();
} else {
loger.error(`会议密码校验-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_JOIN_NETWORK);
throw '';
}
})
.then(ret => {
let rectObj=JSON.parse(ret);
if (rectObj.flag === 'false'||rectObj.flag === false) {
loger.error(`会议密码校验-失败.`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_PASSWORD_WRONG);
return ;
// Sass校验开始-->密码校验(如果需要密码)--->MD5校验----------------------------------------------------
passwordAndMd5Checking(_param) {
loger.log('2.开始Sass校验');
console.log(_param);
confInfo = _param;
// 密码校验
if (confInfo.passwordRequired === 'true' || confInfo.passwordRequired === true) {
this.sendPWDChecking();
return;
}
if (rectObj.flag=== 'true'||rectObj.flag === true) {
loger.log(`会议密码校验-成功.`);
this.sendMD5Checking();
return;
}
loger.error(`会议密码校验-协议异常.`,rectObj);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_JOIN_PROTOCOL);
})
.catch(err => {
loger.error(`会议密码校验-异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_JOIN_FAILED);
});
}
// MD5校验
this.sendMD5Checking();
}
//MD5校验-----------------------------------------------------------------------------------------
sendMD5Checking() {
let url = `http://${confInfo.portal}/3m/meeting/md5CheckMeeting.do?siteId=${confInfo.siteId}&meetingNumber=${confInfo.classId}&userId=${confInfo.userId}&userName=${confInfo.userName}&userType=${confInfo.userType}&nopassword=${confInfo.passwordRequired}&md5=${confInfo.md5}`;
loger.log('4.MD5校验', url);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.status === 200) {
return ret.json();
} else {
loger.error(`MD5校验-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_JOIN_NETWORK);
throw '';
// 入会密码校验---------------------------------------------------------------------------------------
sendPWDChecking() {
//let url = `http://${classInfo.portal}/3m/getCheckMeetinig.do?siteId=${classInfo.siteId}&classId=${classInfo.classId}&password=${classInfo.password}`;
/*
/3m/api/meeting/signIn.do
siteId 站点号
classId 课堂号(meetingNumber)
isTeacher 是否是老师:1 是 0 否
password 输入的密码
// 请求格式 http://112.126.80.182/3m/api/meeting/signIn.do?siteId=h5test&classId=526661904&password=111111&isTeacher=0
*/
//判断是否是老师
let isTeacher = 0;
if (confInfo.userRole == ApeConsts.host) {
isTeacher = 1
}
})
.then(ret => {
if (ret.flag == "true"||ret.flag == true) {
/* if (ret.h5_mcu_list) {
let server = ret.h5_mcu_list.split(";")[0];
confInfo.MCUServerIP = server.split(":")[0];
confInfo.MCUServerPort = server.split(":")[1];
GlobalConfig.MCUServerIP=confInfo.MCUServerIP;
GlobalConfig.MCUServerPort=confInfo.MCUServerPort;
}
confInfo.maxVideoChannels = ret.maxVideoChannels;
confInfo.maxAudioChannels = ret.maxAudioChannels;
confInfo.maxMediaChannels = confInfo.maxVideoChannels + confInfo.maxAudioChannels;
let url = `http://${confInfo.portal}/3m/api/meeting/signIn.do?siteId=${confInfo.siteId}&classId=${confInfo.classId}&isTeacher=${isTeacher}&password=${confInfo.password}`;
loger.log('3.会议密码校验', url);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.status === 200) {
return ret.text();
} else {
loger.error(`会议密码校验-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_NETWORK);
throw '';
}
})
.then(ret => {
let rectObj = JSON.parse(ret);
if (rectObj.flag === 'false' || rectObj.flag === false) {
loger.error(`会议密码校验-失败.`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_PASSWORD_WRONG);
return;
}
if (rectObj.flag === 'true' || rectObj.flag === true) {
loger.log(`会议密码校验-成功.`);
this.sendMD5Checking();
return;
}
loger.error(`会议密码校验-协议异常.`, rectObj);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PROTOCOL);
})
.catch(err => {
loger.error(`会议密码校验-异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FAILED);
});
}
GlobalConfig.maxVideoChannels=confInfo.maxVideoChannels;
GlobalConfig.maxAudioChannels=confInfo.maxAudioChannels;
GlobalConfig.maxMediaChannels=confInfo.maxMediaChannels;*/
loger.log('MD5校验完成');
console.log(ret);
this._emit(Sass.SUCCESS,ret);
} else {
loger.log('MD5校验-失败.');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_MD5_WRONG);
//MD5校验-----------------------------------------------------------------------------------------
sendMD5Checking() {
let url = `http://${confInfo.portal}/3m/meeting/md5CheckMeeting.do?siteId=${confInfo.siteId}&meetingNumber=${confInfo.classId}&userId=${confInfo.userId}&userName=${confInfo.userName}&userType=${confInfo.userType}&nopassword=${confInfo.passwordRequired}&md5=${confInfo.md5}`;
loger.log('4.MD5校验', url);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.status === 200) {
return ret.json();
} else {
loger.error(`MD5校验-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_NETWORK);
throw '';
}
})
.then(ret => {
if (ret.flag == "true" || ret.flag == true) {
/* if (ret.h5_mcu_list) {
let server = ret.h5_mcu_list.split(";")[0];
confInfo.MCUServerIP = server.split(":")[0];
confInfo.MCUServerPort = server.split(":")[1];
}
})
.catch(err => {
loger.error(`MD5校验-异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_CLASS_JOIN_FAILED);
});
}
GlobalConfig.MCUServerIP=confInfo.MCUServerIP;
GlobalConfig.MCUServerPort=confInfo.MCUServerPort;
}
confInfo.maxVideoChannels = ret.maxVideoChannels;
confInfo.maxAudioChannels = ret.maxAudioChannels;
confInfo.maxMediaChannels = confInfo.maxVideoChannels + confInfo.maxAudioChannels;
// 获取会议基本详情------------------------------------------------------------------------------------
getClassDetail() {
let url = `http://${confInfo.portal}/3m/meeting/getClassH5.do?classNumber=${confInfo.classId}`;
loger.log('获取Class详情.', url);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`获取Class详情-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_GET_CLASS_DETAIL);
throw '';
}
})
.then(ret => {
if (ret.errorCode === 0) {
loger.log('获取Class详情完成');
this._emit(Sass.CLASS_GET_CLASS_DETAIL, ret);
} else {
loger.warn('获取Class详情失败.');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_GET_CLASS_DETAIL);
}
})
.catch(err => {
loger.error(`获取Class详情异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_GET_CLASS_DETAIL);
});
}
GlobalConfig.maxVideoChannels=confInfo.maxVideoChannels;
GlobalConfig.maxAudioChannels=confInfo.maxAudioChannels;
GlobalConfig.maxMediaChannels=confInfo.maxMediaChannels;*/
loger.log('MD5校验完成');
console.log(ret);
this._emit(Sass.SUCCESS, ret);
} else {
loger.log('MD5校验-失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_MD5_WRONG);
//获取课堂会议的完整信息--------------------------------------------------------------------------------
getClassParam(){
/*
参数 (application/x-www-form-urlencoded):
名称 类型 可选 默认值 说明
meetingNumber String 否 null 课堂号
timestamp String 否 null 时间戳
authId String 否 null 验证信息 md5(meetingNumber + timestamp)
返回 (application/json):
名称 类型 说明
code int 0 正常
1 课堂号必填
2 无效的课堂号
3 没有对应的站点
4 站点已过期
siteId String 站点号
meetingNumber String 课堂号 对应的是classId
*/
var timestamp=new Date().getTime();
var authId=MD5(confInfo.classId+""+timestamp);//课堂号+时间戳 的字符串,转成MD5
let url = `http://${confInfo.portal}/3m/api/meeting/detail.do?meetingNumber=${confInfo.classId}&timestamp=${timestamp}&authId=${authId}`;
loger.log('5.获取课堂会议的完整信息 ');
console.log(url);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`获取课堂会议的完整信息-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_GET_CLASS_PARAML);
}
})
.catch(err => {
loger.error(`MD5校验-异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FAILED);
});
}
throw '';
}
// 获取会议基本详情------------------------------------------------------------------------------------
getClassDetail() {
let url = `http://${confInfo.portal}/3m/meeting/getClassH5.do?classNumber=${confInfo.classId}`;
loger.log('获取Class详情.', url);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.code === 0) {
loger.log('获取课堂会议的完整信息完成');
this._emit(Sass.CLASS_GET_CLASS_PARAM, ret);
} else {
loger.warn('获取课堂会议的完整信息 失败.');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_GET_CLASS_PARAML);
}
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`获取Class详情-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_DETAIL);
throw '';
}
})
.then(ret => {
if (ret.errorCode === 0) {
loger.log('获取Class详情完成');
this._emit(Sass.CLASS_GET_CLASS_DETAIL, ret);
} else {
loger.warn('获取Class详情失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_DETAIL);
}
})
.catch(err => {
loger.error(`获取Class详情异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_DETAIL);
});
}
//获取课堂会议的完整信息--------------------------------------------------------------------------------
getClassParam() {
/*
参数 (application/x-www-form-urlencoded):
名称 类型 可选 默认值 说明
meetingNumber String 否 null 课堂号
timestamp String 否 null 时间戳
authId String 否 null 验证信息 md5(meetingNumber + timestamp)
返回 (application/json):
名称 类型 说明
code int 0 正常
1 课堂号必填
2 无效的课堂号
3 没有对应的站点
4 站点已过期
siteId String 站点号
meetingNumber String 课堂号 对应的是classId
*/
var timestamp = new Date().getTime();
var authId = MD5(confInfo.classId + "" + timestamp);//课堂号+时间戳 的字符串,转成MD5
let url = `http://${confInfo.portal}/3m/api/meeting/detail.do?meetingNumber=${confInfo.classId}&timestamp=${timestamp}&authId=${authId}`;
loger.log('5.获取课堂会议的完整信息 ');
console.log(url);
fetch(url, {
timeout: 5000
})
.catch(err => {
loger.error(`获取课堂会议的完整信息异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_GET_CLASS_PARAML);
});
}
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`获取课堂会议的完整信息-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
throw '';
}
})
.then(ret => {
if (ret.code === 0) {
loger.log('获取课堂会议的完整信息完成');
this._emit(Sass.CLASS_GET_CLASS_PARAM, ret);
} else {
loger.warn('获取课堂会议的完整信息 失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
}
})
.catch(err => {
loger.error(`获取课堂会议的完整信息异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
});
}
//删除文档-----------------------------------------------------------------------------------------------------
//删除文档-----------------------------------------------------------------------------------------------------
/*
删除课堂中的文档,即删除课堂与文档的关联
删除课堂中的文档,即删除课堂与文档的关联
/api/document/deleteRelation.do
参数
docId 文档的唯一id
classId 课堂号
timestamp 时间戳
authId md5(docId+classId+timestamp)
参数
docId 文档的唯一id
classId 课堂号
timestamp 时间戳
authId md5(docId+classId+timestamp)
返回 (application/json):
0 成功, 1 验证信息错误
*/
sassDeleteDocument(_param){
var timestamp=new Date().getTime();
var authId=MD5(_param.docId+""+_param.classId+""+timestamp);// docId+classId+timestamp的字符串,转成MD5
let url = `http://${confInfo.portal}/3m/api/document/deleteRelation.do?docId=${_param.docId}&classId=${confInfo.classId}&timestamp=${timestamp}&authId=${authId}`;
loger.log('sassDeleteDocument', url);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`sassDeleteDocument-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
0 成功, 1 验证信息错误
*/
sassDeleteDocument(_param) {
var timestamp = new Date().getTime();
var authId = MD5(_param.docId + "" + _param.classId + "" + timestamp);// docId+classId+timestamp的字符串,转成MD5
let url = `http://${confInfo.portal}/3m/api/document/deleteRelation.do?docId=${_param.docId}&classId=${confInfo.classId}&timestamp=${timestamp}&authId=${authId}`;
loger.log('sassDeleteDocument', url);
throw '';
}
})
.then(ret => {
if (ret.code === 0) {
loger.log('sassDeleteDocument 完成');
this._emit(Sass.DELETE_DOCUMENT_SUCCESS, _param);
} else {
loger.warn('sassDeleteDocumnt 失败.');
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
}
fetch(url, {
timeout: 5000
})
.catch(err => {
loger.error(`sassDeleteDocument异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
});
}
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`sassDeleteDocument-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED);
//保存课堂的当前信息-------------------------------------------------------------------------------------------------
/*保存课堂的当前信息,首次是插入,后面是更新
/api/meeting/saveInfo.do
参数(application/x-www-form-urlencoded):
info Json字符串课堂信息,由前端自己维护
classId 课堂号
timestamp 时间戳
authId 做基本验证,md5(classId+timestamp)
throw '';
}
})
.then(ret => {
if (ret.code === 0) {
loger.log('sassDeleteDocument 完成');
this._emit(Sass.DELETE_DOCUMENT_SUCCESS, _param);
} else {
loger.warn('sassDeleteDocumnt 失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED);
}
})
.catch(err => {
loger.error(`sassDeleteDocument异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED);
});
}
返回 (application/json):
code 0 成功 1 课堂号为空 2 无效的课堂号 3 验证信息错误*/
//保存课堂的当前信息-------------------------------------------------------------------------------------------------
/*保存课堂的当前信息,首次是插入,后面是更新
/api/meeting/saveInfo.do
参数(application/x-www-form-urlencoded):
info Json字符串课堂信息,由前端自己维护
classId 课堂号
timestamp 时间戳
authId 做基本验证,md5(classId+timestamp)
saveClassStatusInfo(_param){
//{"classStatusInfo":classStatusInfo}
var timestamp=new Date().getTime();
var authId=MD5(confInfo.classId+""+timestamp);// (classId+timestamp)的字符串,转成MD5
let classStatusInfo=JSON.stringify(_param.classStatusInfo);
let url = `http://${confInfo.portal}/3m/api/meeting/saveInfo.do`;
loger.log('saveClassStatusInfo', url);
fetch(url, {
method: 'POST',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body:`classId=${confInfo.classId}&info=${classStatusInfo}&timestamp=${timestamp}&authId=${authId}`,
timeout: 5000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`saveClassStatusInfo-网络异常.状态码:${ret.status}`);
//this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
throw '';
}
})
.then(ret => {
if (ret.code === 0) {
loger.log('saveClassStatusInfo 完成');
this._emit(Sass.CLASS_SAVE_STATUS_INFO_SUCCESS, _param);
} else if (ret.code ===1) {
loger.log('saveClassStatusInfo 失败 课堂号为空');
}else if (ret.code === 2) {
loger.log('saveClassStatusInfo 失败 无效的课堂号');
}else if (ret.code === 3) {
loger.log('saveClassStatusInfo 失败 验证信息错误');
}else {
loger.warn('saveClassStatusInfo 失败.',ret);
//this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
}
})
.catch(err => {
loger.error(`saveClassStatusInfo.状态码:${err}`);
//this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
});
}
返回 (application/json):
code 0 成功 1 课堂号为空 2 无效的课堂号 3 验证信息错误*/
/*
//用get的方式保存数据
saveClassStatusInfo(_param){
//{"classStatusInfo":"JSON数据的字符串"}
var timestamp=new Date().getTime();
var authId=MD5(confInfo.classId+""+timestamp);// (classId+timestamp)的字符串,转成MD5
let url = `http://${confInfo.portal}/3m/api/meeting/saveInfo.do?classId=${confInfo.classId}&info=${_param.classStatusInfo}&timestamp=${timestamp}&authId=${authId}`;
saveClassStatusInfo(_param) {
//{"classStatusInfo":classStatusInfo}
var timestamp = new Date().getTime();
var authId = MD5(confInfo.classId + "" + timestamp);// (classId+timestamp)的字符串,转成MD5
let classStatusInfo = JSON.stringify(_param.classStatusInfo);
let url = `http://${confInfo.portal}/3m/api/meeting/saveInfo.do`;
loger.log('saveClassStatusInfo', url);
fetch(url, {
timeout: 5000
method: 'POST',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: `classId=${confInfo.classId}&info=${classStatusInfo}&timestamp=${timestamp}&authId=${authId}`,
timeout: 5000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`saveClassStatusInfo-网络异常.状态码:${ret.status}`);
//this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
throw '';
}
if (ret.ok) {
return ret.json();
} else {
loger.error(`saveClassStatusInfo-网络异常.状态码:${ret.status}`);
//this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
throw '';
}
})
.then(ret => {
if (ret.code === 0) {
loger.log('saveClassStatusInfo 完成');
this._emit(Sass.CLASS_SAVE_STATUS_INFO_SUCCESS, _param);
} else if (ret.code ===1) {
loger.log('saveClassStatusInfo 失败 课堂号为空');
}else if (ret.code === 2) {
loger.log('saveClassStatusInfo 失败 无效的课堂号');
}else if (ret.code === 3) {
loger.log('saveClassStatusInfo 失败 验证信息错误');
}else {
loger.warn('saveClassStatusInfo 失败.',ret);
if (ret.code === 0) {
loger.log('saveClassStatusInfo 完成');
this._emit(Sass.CLASS_SAVE_STATUS_INFO_SUCCESS, _param);
} else if (ret.code === 1) {
loger.log('saveClassStatusInfo 失败 课堂号为空');
} else if (ret.code === 2) {
loger.log('saveClassStatusInfo 失败 无效的课堂号');
} else if (ret.code === 3) {
loger.log('saveClassStatusInfo 失败 验证信息错误');
} else {
loger.warn('saveClassStatusInfo 失败.', ret);
//this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
}
})
.catch(err => {
loger.error(`saveClassStatusInfo.状态码:${err}`);
//this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
}
});
}
//保存录制的信息,主要是录制文件的名称,必须和MCU录制的文件名相同
saveClassRecordContrlInfo(_param) {
loger.log('保存开始录制信息');
let key = "3mang123A";
let siteID = GlobalConfig.siteId;
let meetingID = GlobalConfig.classId;
let userID = GlobalConfig.userId;
let userName = GlobalConfig.userName;
let meetingName = GlobalConfig.className;
let startTime =GlobalConfig.classBeginTime;
let endTime = GlobalConfig.classEndTime;
let playUrl = "";
let streamName = GlobalConfig.recordFileName;
let confRecordFileName=GlobalConfig.recordFileName;
let downloadUrl = "";
let recordStatus = GlobalConfig.classStatus;
let recordTimestamp =GlobalConfig.classTimestamp;
let timestamp = new Date().getTime();;
let authId = MD5(key + siteID + meetingID + timestamp);
let url = `http://${confInfo.portal}/3m/recordingMeeting/insertRecordingMeeting.do?siteID=${siteID}&meetingID=${meetingID}&userID=${userID}&userName=${userName}&meetingName=${meetingName}&startTime=${startTime}&endTime=${endTime}&playUrl=${playUrl}&streamName=${streamName}&downloadUrl=${downloadUrl}&configFile=${confRecordFileName}&timestamp=${timestamp}&recordTimestamp=${recordTimestamp}&authId=${authId}`;
loger.log('saveClassRecordContrlInfo', url);
fetch(url, {
timeout: 5000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`保存开始录制信息-网络异常.状态码:${ret.status}`);
throw '';
}
})
.then(ret => {
if (ret.code === 0) {
loger.log('保存开始录制信息 完成');
this._emit(Sass.CLASS_SAVE_RECORD_INFO_SUCCESS, _param);
} else {
loger.warn('保存开始录制信息 失败.');
}
})
.catch(err => {
loger.error(`saveClassStatusInfo.状态码:${err}`);
//this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
loger.error(`保存开始录制信息异常.状态码:${err}`);
});
}*/
}
}
Sass.prototype.SUCCESS = Sass.SUCCESS = 'Sass.success';
Sass.prototype.CLASS_INIT_SUCCESS = Sass.CLASS_INIT_SUCCESS = 'sass.class.init.success';
Sass.prototype.CLASS_GET_CLASS_PARAM= Sass.CLASS_GET_CLASS_PARAM = 'class.getClassParam.message';
Sass.prototype.CLASS_GET_CLASS_DETAIL= Sass.CLASS_GET_CLASS_DETAIL = 'class.getClassDetail.message';
Sass.prototype.DELETE_DOCUMENT_SUCCESS= Sass.DELETE_DOCUMENT_SUCCESS = 'class.deleteDocumentSuccess.message';//删除文档成功
Sass.prototype.CLASS_GET_CLASS_PARAM = Sass.CLASS_GET_CLASS_PARAM = 'class.getClassParam.message';
Sass.prototype.CLASS_GET_CLASS_DETAIL = Sass.CLASS_GET_CLASS_DETAIL = 'class.getClassDetail.message';
Sass.prototype.DELETE_DOCUMENT_SUCCESS = Sass.DELETE_DOCUMENT_SUCCESS = 'class.deleteDocumentSuccess.message';//删除文档成功
Sass.prototype.CLASS_SAVE_STATUS_INFO_SUCCESS = Sass.CLASS_SAVE_STATUS_INFO_SUCCESS = 'class.saveClassStatusInfoSuccess.message';//保存会议状态信息
Sass.prototype.CLASS_SAVE_RECORD_INFO_SUCCESS = Sass.CLASS_SAVE_RECORD_INFO_SUCCESS = 'class.saveClassRecordInfoSuccess.message';//保存录制会议信息
Sass.prototype.CLASS_SAVE_STATUS_INFO_SUCCESS= Sass.CLASS_SAVE_STATUS_INFO_SUCCESS = 'class.saveClassStatusInfoSuccess.message';//保存会议状态信息
export default new Sass;
... ...
... ... @@ -2,25 +2,13 @@
// 计时器
// //////////////////////////////////////////////////////////////////////////////
//import ApeConsts from './ApeConsts';
//import Loger from 'Loger';
//import MessageTypes from 'MessageTypes';
//import GlobalConfig from 'GlobalConfig';
//import EngineUtils from 'EngineUtils';
//let loger = Loger.getLoger('MediaModule');
/*let counter=0;
let callBackDelay=1;
let callBackFun;
let isStart=false;*/
class TimerCounter {
constructor() {
this.timer=0;
this.delay=1000;
this.counter=0;
this.callBackDelay=1;
this.callBackFun=null;
this.callBackDelay=1;//回调间隔,单位(秒)
this.callBackFun=null;//回调函数
this.isStart=false;
}
... ...
... ... @@ -55,6 +55,7 @@ class ConferApe extends Ape {
this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
this.on(pdu.RCPDU_CONFERENCE_SEND_DATA_REQUEST, this.conferMsgComingHandler.bind(this));//这个是会议消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
this.on(pdu.RCPDU_CONFERENCE_RECORD_REQUEST,this.onSendConferRecordRequestHandler.bind(this));//发送录制和停止录制消息
}
//加入会议
... ... @@ -114,27 +115,87 @@ class ConferApe extends Ape {
}
*/
let chatSendPdu = new pdu['RCConferenceSendDataRequestPdu'];
chatSendPdu.type = pdu.RCPDU_CONFERENCE_SEND_DATA_REQUEST;
chatSendPdu.initiator = this._classInfo.nodeId;//发起人
chatSendPdu.peer = parseInt(_messageInfo.to);//发送给谁,公聊的时候是0,私聊的时候是指定的用户id
chatSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message);
//chatSendPdu.userData =UTF8.setBytesFromString(_messageInfo.message);
chatSendPdu.isPublic = true;
chatSendPdu.actionType=_messageInfo.actionType;
// if (!(chatSendPdu.isPublic || 0 === chatSendPdu.peer)) {
if (!chatSendPdu.isPublic && 0!=chatSendPdu.peer) {
let conferSendPdu = new pdu['RCConferenceSendDataRequestPdu'];
conferSendPdu.type = pdu.RCPDU_CONFERENCE_SEND_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(chatSendPdu);
this.send(conferSendPdu);
} else {
//发送给所有人
loger.log('发送公聊会议消息.');
this.sendChatUniform(chatSendPdu);
this.sendChatUniform(conferSendPdu);
}
}
//发送录制或停止录制的消息,{"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);
}
//开启录制
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);
}
}
//主动离开会议,发送通知到服务器
leaveClass(){
let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
... ... @@ -169,32 +230,48 @@ class ConferApe extends Ape {
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){
let timestamp=EngineUtils.creatTimestampStr();
GlobalConfig.classStopTime=timestamp;
if(GlobalConfig.isHost){
if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_WAIT){
GlobalConfig.classStartTime=timestamp;
}
let timestamp=EngineUtils.creatTimestampStr();
GlobalConfig.classStopTime=timestamp;
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_STARTED;
//_param.actionType=ACTION_TYPE_1;
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this.sendUpdaterClassStatusInfo({"actionType":1});
//如果录制的文件名不存在,需要创建一个名字
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();
//开始计时
this.startTimerCounter();
}else {
loger.warn('没有权限');
}
}
//暂停上课
pauseClass(_param){
... ... @@ -205,7 +282,8 @@ class ConferApe extends Ape {
GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_PAUSE;
GlobalConfig.classStopTime=EngineUtils.creatTimestampStr();
//_param.actionType=ACTION_TYPE_2;
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this.sendUpdaterClassStatusInfo({"actionType":2});
this.stopTimerCounter();
... ... @@ -280,12 +358,15 @@ class ConferApe extends Ape {
/////收到消息处理/////////////////////////////////////////////////////////////////////////////////
//加入channel成功
onJoinChannelHandlerSuccess(){
loger.log('ConferApe 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();
}
}
//开启计时器
... ... @@ -307,7 +388,7 @@ class ConferApe extends Ape {
return;
}
GlobalConfig.classTimestamp=GlobalConfig.classTimestamp+1;//计时
loger.log('课堂进行时间',GlobalConfig.classTimestamp);
//loger.log('课堂进行时间',GlobalConfig.classTimestamp);
this._emit(MessageTypes.CLASS_UPDATE_TIMER,{"classTimestamp":GlobalConfig.classTimestamp});
if(GlobalConfig.classTimestamp%GlobalConfig.updateClassInfoDelay==0){
... ... @@ -380,6 +461,17 @@ class ConferApe extends Ape {
}
}
onSendConferRecordRequestHandler(_data){
loger.log("onSendConferRecordRequestHandler");
try{
let conferRecordSendPdu =pdu['RCConferenceRecordRequestPdu'].decode(_data);
console.log(conferRecordSendPdu);
}catch (err){
loger.warn("onSendConferRecordRequestHandler err",err.message);
}
}
rosterInsertHandler(nodeId, nodeData) {
if(GlobalConfig.nodeId==nodeId){
loger.log("自己加入 rosterInsertHandler");
... ...
... ... @@ -25,7 +25,7 @@ class MediaModule {
_param.channelId == null|| _param.timestamp==null)
{
loger.warn('getMediaPlayPath,参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
//this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return {"code": ApeConsts.RETURN_FAILED, "data": ""};
}
... ...
... ... @@ -88,6 +88,7 @@ RCPduPackage.RCPDU_AUDIO_SEND_DATA_REQUEST = 261;
RCPduPackage.RCPDU_GIFT_SEND_DATA_REQUEST = 262;
RCPduPackage.RCPDU_CHAT_SEND_DATA_REQUEST = 263;
RCPduPackage.RCPDU_VOTING_POLL_RECORD = 265;
RCPduPackage.RCPDU_CONFERENCE_RECORD_REQUEST = 270;//录制和停止录制的协议号
RCPduPackage.RCPDU_REG_REQUEST_OBJ = 290;
RCPduPackage.RCPDU_REG_RESPONSE_OBJ = 291;
... ...
... ... @@ -121,6 +121,7 @@ enum RCPduType_E {
RCPDU_GIFT_SEND_DATA_REQUEST = 262;
RCPDU_CHAT_SEND_DATA_REQUEST = 263;
RCPDU_VOTING_POLL_RECORD = 265;
RCPDU_CONFERENCE_RECORD_REQUEST = 270;
// Registry resource request or response PDU
RCPDU_REG_REQUEST_OBJ = 290;
... ... @@ -924,6 +925,12 @@ message RCClassStatusInfoPdu {
optional uint32 active_doc_cur_page=21;//当前激活的文档的当前页
}
message RCConferenceRecordRequestPdu {
optional uint32 initiator = 1; // 发起录像指令的node id
optional bool record = 2; // 录像指令 true:开始录像, false:停止录像
optional uint32 class_time = 3; // 课堂进行时间(秒)
optional string filename = 4; // 录像文件名称,filename中增加目录部分
}
//end
`;
... ...