李勇

Merge branch 'mcuClientBranch'

要显示太多修改。

为保证性能只显示 32 of 32+ 个文件。

此 diff 太大无法显示。
root: true
env:
es6: true
node: true
browser: true
mocha: true
ecmaFeatures:
modules: true
extends:
"airbnb"
rules:
quotes: 0
func-names: 0
comma-dangle: 0
no-new-func: 0
no-eq-null: 0
no-param-reassign: 0
... ...
.DS_Store
*.log
node_modules
src
test
examples
coverage
... ...
language: node_js
node_js:
- "iojs"
... ...
1.0.6 / 2017-2-3
==================
* update typescript config
1.0.5 / 2016-12-29
==================
* update typescript support
1.0.4 / 2016-12-23
==================
* add typescript support
1.0.3 / 2016-12-04
==================
* add examples index-ie8.html
* remove `es6-promise` dependent
1.0.2 / 2016-09-26
==================
* Use original url when Request error
1.0.1 / 2016-08-14
==================
* Format code
* Update Readme
1.0.0 / 2015-11-19
==================
* Remove Bower support
* Add jsonpCallback and jsonpCallbackFunction as options
0.9.2 / 2015-08-11
==================
* Remove global export of fetchJsonp
0.9.1 / 2015-08-11
==================
* Update removeScript fix legacy IE
... ...
# Maintaining
## Releasing a new version
This project follows [semver](http://semver.org/). So if you are making a bug
fix, only increment the patch level "1.0.x". If any new files are added, a
minor version "1.x.x" bump is in order.
### Make a release commit
To prepare the release commit:
1. Change the npm [package.json](https://github.com/camsong/fetch-jsonp/blob/master/package.json)
`version` value to match.
2. Make a single commit with the description as "Fetch JSONP 1.x.x".
3. Finally, tag the commit with `v1.x.x`.
```
$ git pull
$ vim package.json
$ git add package.json
$ git commit -m "Fetch JSONP 1.x.x"
$ git tag v1.x.x
$ git push
$ git push --tags
```
... ...
# Fetch JSONP [![Build Status](https://travis-ci.org/camsong/fetch-jsonp.svg)](https://travis-ci.org/camsong/fetch-jsonp) [![npm version](https://badge.fury.io/js/fetch-jsonp.svg)](http://badge.fury.io/js/fetch-jsonp) [![npm downloads](https://img.shields.io/npm/dm/fetch-jsonp.svg?style=flat-square)](https://www.npmjs.com/package/fetch-jsonp)
JSONP is NOT supported in standard Fetch API, https://fetch.spec.whatwg.org.
fetch-jsonp provides you same API to fetch JSONP like naive Fetch, also comes
with global `fetchJsonp` function.
If you need a `fetch` polyfill for old browsers, try [github/fetch](http://github.com/github/fetch).
## Installation
You can install with `npm`.
```
npm install fetch-jsonp
```
## Promise Polyfill for IE
IE8/9/10/11 does not support [ES6 Promise](https://tc39.github.io/ecma262/#sec-promise-constructor), run this to polyfill the global environment at the beginning of your application.
```js
require('es6-promise').polyfill();
```
## Usage
The `fetch-jsonp` function supports any HTTP method. We'll focus on GET and POST
example requests.
### Fetch JSONP in simple way
```javascript
fetchJsonp('/users.jsonp')
.then(function(response) {
return response.json()
}).then(function(json) {
console.log('parsed json', json)
}).catch(function(ex) {
console.log('parsing failed', ex)
})
```
### Set JSONP callback name, default is 'callback'
```javascript
fetchJsonp('/users.jsonp', {
jsonpCallback: 'custom_callback'
})
.then(function(response) {
return response.json()
}).then(function(json) {
console.log('parsed json', json)
}).catch(function(ex) {
console.log('parsing failed', ex)
})
```
### Set JSONP request timeout, default is 5000ms
```javascript
fetchJsonp('/users.jsonp', {
timeout: 3000,
jsonpCallback: 'custom_callback'
})
.then(function(response) {
return response.json()
}).then(function(json) {
console.log('parsed json', json)
}).catch(function(ex) {
console.log('parsing failed', ex)
})
```
### Caveats
You need to call `.then(function(response) { return response.json(); })` in order
to keep consistent with Fetch API.
## Browser Support
![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 8+ ✔ | Latest ✔ | 6.1+ ✔ |
# License
MIT
# Acknowledgement
Thanks to [github/fetch](https://github.com/github/fetch) for bring Fetch to old browsers.
... ...
(function (global, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports', 'module'], factory);
} else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
factory(exports, module);
} else {
var mod = {
exports: {}
};
factory(mod.exports, mod);
global.fetchJsonp = mod.exports;
}
})(this, function (exports, module) {
'use strict';
var defaultOptions = {
timeout: 5000,
jsonpCallback: 'callback',
jsonpCallbackFunction: null
};
function generateCallbackFunction() {
return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
}
// Known issue: Will throw 'Uncaught ReferenceError: callback_*** is not defined'
// error if request timeout
function clearFunction(functionName) {
// IE8 throws an exception when you try to delete a property on window
// http://stackoverflow.com/a/1824228/751089
try {
delete window[functionName];
} catch (e) {
window[functionName] = undefined;
}
}
function removeScript(scriptId) {
var script = document.getElementById(scriptId);
document.getElementsByTagName('head')[0].removeChild(script);
}
function fetchJsonp(_url) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
// to avoid param reassign
var url = _url;
var timeout = options.timeout || defaultOptions.timeout;
var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
var timeoutId = undefined;
return new Promise(function (resolve, reject) {
var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
var scriptId = jsonpCallback + '_' + callbackFunction;
window[callbackFunction] = function (response) {
resolve({
ok: true,
// keep consistent with fetch API
json: function json() {
return Promise.resolve(response);
}
});
if (timeoutId) clearTimeout(timeoutId);
removeScript(scriptId);
clearFunction(callbackFunction);
};
// Check if the user set their own params, and if not add a ? to start a list of params
url += url.indexOf('?') === -1 ? '?' : '&';
var jsonpScript = document.createElement('script');
jsonpScript.setAttribute('src', '' + url + jsonpCallback + '=' + callbackFunction);
jsonpScript.id = scriptId;
document.getElementsByTagName('head')[0].appendChild(jsonpScript);
timeoutId = setTimeout(function () {
reject(new Error('JSONP request to ' + _url + ' timed out'));
clearFunction(callbackFunction);
removeScript(scriptId);
}, timeout);
});
}
// export as global function
/*
let local;
if (typeof global !== 'undefined') {
local = global;
} else if (typeof self !== 'undefined') {
local = self;
} else {
try {
local = Function('return this')();
} catch (e) {
throw new Error('polyfill failed because global object is unavailable in this environment');
}
}
local.fetchJsonp = fetchJsonp;
*/
module.exports = fetchJsonp;
});
\ No newline at end of file
... ...
declare function fetchJsonp(url: string, options?: fetchJsonp.Options): Promise<fetchJsonp.Response>;
declare namespace fetchJsonp {
interface Options {
timeout?: number;
jsonpCallback?: string;
jsonpCallbackFunction?: string;
}
interface Response {
json(): Promise<any>;
json<T>(): Promise<T>;
ok: boolean;
}
}
export = fetchJsonp;
... ...
{
"_args": [
[
"fetch-jsonp",
"D:\\work\\McuClient"
]
],
"_from": "fetch-jsonp@latest",
"_id": "fetch-jsonp@1.0.6",
"_inCache": true,
"_installable": true,
"_location": "/fetch-jsonp",
"_nodeVersion": "5.7.1",
"_npmOperationalInternal": {
"host": "packages-12-west.internal.npmjs.com",
"tmp": "tmp/fetch-jsonp-1.0.6.tgz_1486087842804_0.46444737794809043"
},
"_npmUser": {
"email": "neosoyn@gmail.com",
"name": "camsong"
},
"_npmVersion": "3.6.0",
"_phantomChildren": {},
"_requested": {
"name": "fetch-jsonp",
"raw": "fetch-jsonp",
"rawSpec": "",
"scope": null,
"spec": "latest",
"type": "tag"
},
"_requiredBy": [
"#USER"
],
"_resolved": "https://registry.npmjs.org/fetch-jsonp/-/fetch-jsonp-1.0.6.tgz",
"_shasum": "8d2ae174ed14108292f025f43fa07d2078de6736",
"_shrinkwrap": null,
"_spec": "fetch-jsonp",
"_where": "D:\\work\\McuClient",
"author": {
"name": "Cam Song"
},
"bugs": {
"url": "https://github.com/camsong/fetch-jsonp/issues"
},
"dependencies": {},
"description": "Fetch JSONP like a boss using Fetch API",
"devDependencies": {
"babel": "^5.8.21",
"babel-core": "^5.8.21",
"babel-eslint": "^4.0.5",
"chai": "^3.2.0",
"eslint": "^1.1.0",
"eslint-config-airbnb": "^0.0.7",
"eslint-plugin-react": "^3.2.1",
"mocha": "^2.2.5"
},
"directories": {},
"dist": {
"shasum": "8d2ae174ed14108292f025f43fa07d2078de6736",
"tarball": "https://registry.npmjs.org/fetch-jsonp/-/fetch-jsonp-1.0.6.tgz"
},
"gitHead": "3b1be53776fa36a548fbf2aa16063c27ca318661",
"homepage": "https://github.com/camsong/fetch-jsonp#readme",
"keywords": [
"fetch",
"jsonp",
"github fetch",
"ajax"
],
"license": "MIT",
"main": "build/fetch-jsonp.js",
"maintainers": [
{
"email": "neosoyn@gmail.com",
"name": "camsong"
}
],
"name": "fetch-jsonp",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/camsong/fetch-jsonp.git"
},
"scripts": {
"build": "babel src/ --modules umd --out-dir build",
"clean": "rm -rf build",
"lint": "eslint src/ test/",
"test": "mocha --compilers js:babel/register --recursive --ui bdd --reporter spec"
},
"version": "1.0.6"
}
... ...
# exclude all
/*
# project structure
!/src/
!/etc/
!/doc/
!/test/
!/dist/
# project files
!.gitignore
!README.md
!package.json
!LICENSE
!webpack.config.umd.js
... ...
iphunter
to hunt a fatest http response.
# usage
iphunter(iplist,check_call_back[,timeout]);
```javascript
import iphunter from 'iphunter';
iphunter([
'192.168.99.199',
'baidu.com',
'aliyun.com',
'qq.com',
'192.168.99.100',
'127.0.0.0:8080',
'192.168.1.48:8080',
'localhost:8080'
], function (fatest_ip_response) {
if(!fatest_ip_response) return console.error('nothing!');
console.log('done -> ', fatest_ip_response);
},3000)
```
... ...
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>UMD PLAYGROUND</title></head><body><div id="stage"></div><script type="text/javascript" src="main.js"></script></body></html>
\ No newline at end of file
... ...
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.iphunter=t():e.iphunter=t()}(this,function(){return function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3;if(!(e&&e.length&&t))throw new Error("ips and callback are required.");new o(e,t,n)}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();t.default=i;var o=function(){function e(t,i,r){n(this,e),this.ip="",this.ipcallback=i,this.timeoutId=null,this.reqsCache=[];for(var o=0;o<t.length;o++)this.reqsCache.push(this.send(t[o],r-10));this.timeoutId=setTimeout(this.notify.bind(this),r)}return r(e,[{key:"clearAll",value:function(){this.reqsCache&&this.reqsCache.length&&this.reqsCache.forEach(function(e){e.abort()}),clearTimeout(this.timeoutId),this.ip="",this.ipcallback=null,this.timeoutId=null,this.reqsCache=[]}},{key:"clearReq",value:function(e){this.reqsCache.splice(this.reqsCache.indexOf(e),1)}},{key:"notify",value:function(){this.ipcallback(this.ip),this.clearAll()}},{key:"send",value:function(e,t){var n=this,i=new XMLHttpRequest;return i.open("HEAD","//"+e+"/?_="+Date.now()),i.timeout=t,i.onload=function(){n.ip=e,n.clearReq(i),i.onload=null,n.notify()},i.ontimeout=function(){n.clearReq(i),i.ontimeout=null},i.onerror=function(){n.clearReq(i),i.onerror=null},i.onabort=function(){n.clearReq(i),i.onabort=null},i.send(),i}}]),e}();(function(){"undefined"!=typeof __REACT_HOT_LOADER__&&(__REACT_HOT_LOADER__.register(o,"IpHunter","/Users/AlexWang/ws/iphunter/src/main.js"),__REACT_HOT_LOADER__.register(i,"check","/Users/AlexWang/ws/iphunter/src/main.js"))})()}])});
\ No newline at end of file
... ...
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>UMD PLAYGROUND</title></head><body><div id="stage"></div><script type="text/javascript" src="test.js"></script></body></html>
\ No newline at end of file
... ...
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.iphunter=t():e.iphunter=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return e[o].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(2)},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3;if(!(e&&e.length&&t))throw new Error("ips and callback are required.");new r(e,t,n)}Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}();t.default=o;var r=function(){function e(t,o,i){n(this,e),this.ip="",this.ipcallback=o,this.timeoutId=null,this.reqsCache=[];for(var r=0;r<t.length;r++)this.reqsCache.push(this.send(t[r],i-10));this.timeoutId=setTimeout(this.notify.bind(this),i)}return i(e,[{key:"clearAll",value:function(){this.reqsCache&&this.reqsCache.length&&this.reqsCache.forEach(function(e){e.abort()}),clearTimeout(this.timeoutId),this.ip="",this.ipcallback=null,this.timeoutId=null,this.reqsCache=[]}},{key:"clearReq",value:function(e){this.reqsCache.splice(this.reqsCache.indexOf(e),1)}},{key:"notify",value:function(){this.ipcallback(this.ip),this.clearAll()}},{key:"send",value:function(e,t){var n=this,o=new XMLHttpRequest;return o.open("HEAD","//"+e+"/?_="+Date.now()),o.timeout=t,o.onload=function(){n.ip=e,n.clearReq(o),o.onload=null,n.notify()},o.ontimeout=function(){n.clearReq(o),o.ontimeout=null},o.onerror=function(){n.clearReq(o),o.onerror=null},o.onabort=function(){n.clearReq(o),o.onabort=null},o.send(),o}}]),e}();(function(){"undefined"!=typeof __REACT_HOT_LOADER__&&(__REACT_HOT_LOADER__.register(r,"IpHunter","/Users/AlexWang/ws/iphunter/src/main.js"),__REACT_HOT_LOADER__.register(o,"check","/Users/AlexWang/ws/iphunter/src/main.js"))})()},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}var i=n(1),r=o(i);(0,r.default)(["192.168.99.199","baidu.com","aliyun.com","qq.com","192.168.99.100","127.0.0.0:8080","192.168.1.48:8080","localhost:8080"],function(e){console.log("done -> ",e)});(function(){"undefined"==typeof __REACT_HOT_LOADER__})()}])});
\ No newline at end of file
... ...
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>UMD PLAYGROUND</title>
</head>
<body>
<div id="stage"></div>
</body>
</html>
... ...
{
"_args": [
[
"iphunter",
"D:\\work\\McuClient"
]
],
"_from": "iphunter@latest",
"_id": "iphunter@1.0.6",
"_inCache": true,
"_installable": true,
"_location": "/iphunter",
"_nodeVersion": "6.9.1",
"_npmOperationalInternal": {
"host": "packages-12-west.internal.npmjs.com",
"tmp": "tmp/iphunter-1.0.6.tgz_1488779370023_0.8911087329033762"
},
"_npmUser": {
"email": "1669499355@qq.com",
"name": "xinwangwang"
},
"_npmVersion": "3.10.8",
"_phantomChildren": {},
"_requested": {
"name": "iphunter",
"raw": "iphunter",
"rawSpec": "",
"scope": null,
"spec": "latest",
"type": "tag"
},
"_requiredBy": [
"#USER"
],
"_resolved": "https://registry.npmjs.org/iphunter/-/iphunter-1.0.6.tgz",
"_shasum": "6b7559d73002bd8cc93d558a604d64518d180840",
"_shrinkwrap": null,
"_spec": "iphunter",
"_where": "D:\\work\\McuClient",
"author": {
"name": "AlexWang"
},
"dependencies": {},
"description": "to hunt a fatest http response.",
"devDependencies": {},
"directories": {
"doc": "doc",
"test": "test"
},
"dist": {
"shasum": "6b7559d73002bd8cc93d558a604d64518d180840",
"tarball": "https://registry.npmjs.org/iphunter/-/iphunter-1.0.6.tgz"
},
"gitHead": "c9958f825f514736bd0451f632c227db4bf0a7b7",
"keywords": [
"ipcheck"
],
"license": "MIT",
"main": "dist/main.js",
"maintainers": [
{
"email": "1669499355@qq.com",
"name": "xinwangwang"
}
],
"name": "iphunter",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"scripts": {
"test": "test/index.js"
},
"version": "1.0.6",
"wbp": {
"build": "dist/",
"entries": {
"main": "./src/main.js",
"test": "./test/test.js"
},
"project": "umd",
"source": "src/"
}
}
... ...
class IpHunter {
constructor(ips, callback, timeout) {
this.ip = '';
this.ipcallback = callback;
this.timeoutId = null;
this.reqsCache = [];
for (let i = 0; i < ips.length; i++) {
this.reqsCache.push(this.send(ips[i], timeout - 10));
}
this.timeoutId = setTimeout(this.notify.bind(this), timeout);
}
clearAll() {
if (this.reqsCache && this.reqsCache.length) {
this.reqsCache.forEach((req) => {
req.abort();
})
}
clearTimeout(this.timeoutId);
this.ip = '';
this.ipcallback = null;
this.timeoutId = null;
this.reqsCache = [];
}
clearReq(req) {
this.reqsCache.splice(this.reqsCache.indexOf(req), 1);
}
notify() {
this.ipcallback(this.ip);
this.clearAll();
}
send(pip, timeout) {
const req = new XMLHttpRequest();
req.open('HEAD', `//${pip}/?_=${Date.now()}`);
req.timeout = timeout;
req.onload = () => {
this.ip = pip;
this.clearReq(req);
req.onload = null;
this.notify();
}
req.ontimeout = () => {
this.clearReq(req);
req.ontimeout = null;
}
req.onerror = () => {
this.clearReq(req);
req.onerror = null;
}
req.onabort = () => {
this.clearReq(req);
req.onabort = null;
}
req.send();
return req
}
}
/**
* ips check
* @param {array} ips
* @param {number} callback
* @return {null}
*/
export default function check(ips, callback, timeout = 3000) {
if (!(ips && ips.length && callback)) throw new Error('ips and callback are required.');
new IpHunter(ips, callback, timeout);
}
... ...
import check from 'main.js';
check([
'192.168.99.199',
'baidu.com',
'aliyun.com',
'qq.com',
'192.168.99.100',
'127.0.0.0:8080',
'192.168.1.48:8080',
'localhost:8080'
], function (ip) {
console.log('done -> ', ip);
})
... ...
module.exports = function (umdConf) {
umdConf.devServer.host = '0.0.0.0';
umdConf.webpackFeatures.enableEntryHTML();
umdConf.output.publicPath = '';
if (umdConf.devMode) {
umdConf.webpackFeatures.enableEntryHot('test');
} else {
umdConf.webpackFeatures.enableUglifyJs({
comments: false
});
}
// console.log(umdConf);
};
... ...
... ... @@ -23,13 +23,13 @@ export default class Emiter {
}
}
}
_emit(eid, data) {
_emit(eid, data,data2) {
if (eid) {
//eid=* broadcast
let asteriskStub =this.MAPS['*'];
if (asteriskStub && asteriskStub.length) {
asteriskStub.forEach(function (elistener) {
elistener(eid, data);
elistener(eid, data,data2);
})
}
... ... @@ -37,7 +37,7 @@ export default class Emiter {
let stub = this.MAPS[eid];
if (stub && stub.length) {
stub.forEach(function (elistener) {
elistener(data);
elistener(data,data2);
});
}
}
... ...
... ... @@ -5,6 +5,9 @@ require('string.fromcodepoint');
import Emiter from './Emiter';
import Sass from 'Sass';
import ServerCheck from 'ServerCheck';
import RecordPlayBackParse from 'RecordPlayBackParse';
import MD5 from "md5";
import Mcu from 'mcu';
import MessageTypes from 'MessageTypes';
import Loger from 'Loger';
... ... @@ -19,1014 +22,1128 @@ import GlobalConfig from 'GlobalConfig';
import ApeConsts from 'apes/ApeConsts';
import Base64 from 'base64-js';
import ArrayBufferUtil from 'libs/ArrayBufferUtil';
import UTF8 from 'utf-8';
let loger = Loger.getLoger('MessageEntrance');
let _sdkInfo={"version":"v.1.0.1","author":"www.3mang.com"};
let _sdkInfo = {"version": "v.1.8.0.20170314-1", "author": "www.3mang.com"};
//APE
let _sass;
let _mcu ;
let _serverCheck;
let _mcu;
let _confer_ape;
let _chat_ape;
let _video_ape;
let _audio_ape;
let _doc_ape;
let _whiteboard_ape;
////初始化成功回调函数
//let _initSuccessCallBackFun;
//
////加入会议成功回调函数
//let _joinClassSuccessCallBackFun;
//
////监听mcu所有错误异常回调函数
//let _mcuErrorCallBackFun;
let _parseBuf;
//MCUClient 外部实例化主类
export default class MessageEntrance extends Emiter {
constructor() {
super();
//sdk 信息
this.sdkInfo = _sdkInfo;
loger.log(this.sdkInfo);
//初始化状态
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_0);
//全局的Error处理
this.on(MessageTypes.MCU_ERROR, this._mcuErrorHandler.bind(this));
// Sass平台层
_sass = Sass;
_sass.on('*', (type, data) => this._emit(type, data));
_sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5)
_sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this));//获取会议初始化信息
_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消息层
_mcu = Mcu;
_mcu.on('*', (type, data) => this._emit(type, data));
_mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this));//加入MCU会议完成
// 注册所有应用Ape
_confer_ape = new ConferApe();
_confer_ape.on('*', (type, data) => this._emit(type, data));
_confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件
_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();
_chat_ape.on('*', (type, data) => this._emit(type, data));
_video_ape = new VideoApe();
_video_ape.on('*', (type, data) => this._emit(type, data));
//_video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this));
_audio_ape= new AudioApe();
_audio_ape.on('*', (type, data) => this._emit(type, data));
//_audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this));
_whiteboard_ape = new WhiteBoardApe();
_whiteboard_ape.on('*', (type, data) => this._emit(type, data));
//_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this));
_doc_ape = new DocApe();
_doc_ape.on('*', (type, data) => this._emit(type, data));
_doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this));
_doc_ape.on(MessageTypes.DOC_DELETE, this.docDeleteHandler.bind(this));
_doc_ape.on(DocApe.DOC_JOIN_CHANNEL_SUCCESS, this.docJoinChannelSuccess.bind(this));
//公开外部调用的方法
//class
this.init = this._init.bind(this);
this.joinClass = this._joinClass.bind(this);
this.leaveClass = this._leaveClass.bind(this);
this.getMcuClientStatus = this._getMcuClientStatus.bind(this);
//this.getClassDetail = this._getClassDetail;//停用
this.getClassStatusInfo = this._getClassStatusInfo.bind(this);
this.sendStartClass = this._sendStartClass.bind(this);
this.sendPauseClass = this._sendPauseClass.bind(this);
this.sendCloseClass = this._sendCloseClass.bind(this);
//chatApe
this.sendChatMsg = this._sendChatMsg.bind(this);
//videoApe
this.getVideoPlayPath = this._getVideoPlayPath.bind(this);
this.getVideoPublishPath = this._getVideoPublishPath.bind(this);
this.publishVideo = this._publishVideo.bind(this);
this.stopPublishVideo = this._stopPublishVideo.bind(this);
this.sendVideoBroadcastMsg=this._sendVideoBroadcastMsg.bind(this);
//audioApe
this.getAudioPlayPath = this._getPlayAudioPath.bind(this);
this.getAudioPublishPath = this._getPublishAudioPath.bind(this);
this.publishAudio = this._publishAudio.bind(this);
this.stopPublishAudio = this._stopPublishAudio.bind(this);
this.sendAudioBroadcastMsg=this.sendAudioCommandMsg.bind(this);
//whiteBoradApe
this.sendInsertAnnotaion = this._sendInsertAnnotaion.bind(this);
//this.sendDeleteAnnotaion=this._sendDeleteAnnotaion;
this.sendDeleteAllAnnotation = this._sendDeleteAllAnnotation.bind(this);
this.sendDeleteCurPageAnnotation = this._sendDeleteCurPageAnnotation.bind(this);
this.sendGotoPrev = this._sendGotoPrev.bind(this);
constructor() {
super();
//sdk 信息
this.sdkInfo = _sdkInfo;
loger.log(this.sdkInfo);
//初始化状态
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_0);
//全局的Error处理
this.on(MessageTypes.MCU_ERROR, this._mcuErrorHandler.bind(this));
// Sass平台层
_sass = Sass;
_sass.on('*', (type, data) => this._emit(type, data));
_sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5)
_sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this));//获取课堂初始化信息
//_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删除文档成功
//ServerCheck ip
_serverCheck = ServerCheck;
_serverCheck.on(_serverCheck.SEVER_CHECK_BEST_IP_SUCCESS, this._serverCheckBestIpSuccessHandler.bind(this));//ip选点,获取最佳ip完成
// 底层MCU消息层
_mcu = Mcu;
_mcu.on('*', (type, data) => this._emit(type, data));
_mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this));//加入MCU课堂完成
//录制回放
_parseBuf = RecordPlayBackParse;
_parseBuf.on('*', (type, data) => this._emit(type, data));
_parseBuf.on(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, this._joinRecordPlaybackSuccessHandler.bind(this));//加入录制回放完成
// 注册所有应用Ape
_confer_ape = new ConferApe();
_confer_ape.on('*', (type, data) => this._emit(type, data));
_confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件
_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();
_chat_ape.on('*', (type, data) => this._emit(type, data));
_video_ape = new VideoApe();
_video_ape.on('*', (type, data) => this._emit(type, data));
_video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this));//这个监听事件不能删除,需要通知课堂模块,检查channel占用
_audio_ape = new AudioApe();
_audio_ape.on('*', (type, data) => this._emit(type, data));
_audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this));//这个监听事件不能删除,需要通知课堂模块,检查channel占用
_whiteboard_ape = new WhiteBoardApe();
_whiteboard_ape.on('*', (type, data) => this._emit(type, data));
//_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this));
_doc_ape = new DocApe();
_doc_ape.on('*', (type, data) => this._emit(type, data));
_doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this));
_doc_ape.on(MessageTypes.DOC_DELETE, this.docDeleteHandler.bind(this));
_doc_ape.on(DocApe.DOC_JOIN_CHANNEL_SUCCESS, this.docJoinChannelSuccess.bind(this));
//公开外部调用的方法
//class
this.init = this._init.bind(this);
this.joinClass = this._joinClass.bind(this);
this.leaveClass = this._leaveClass.bind(this);
this.getMcuClientStatus = this._getMcuClientStatus.bind(this);
//this.getClassDetail = this._getClassDetail;//停用
this.getClassStatusInfo = this._getClassStatusInfo.bind(this);
this.sendStartClass = this._sendStartClass.bind(this);
this.sendPauseClass = this._sendPauseClass.bind(this);
this.sendCloseClass = this._sendCloseClass.bind(this);
//录制回放
this.initRecordPlayback = this._initRecordPlayback.bind(this);
this.startRecordPlayback = this._startRecordPlayback.bind(this);
this.stopRecordPlayback = this._stopRecordPlayback.bind(this);
this.pauseRecordPlayback = this._pauseRecordPlayback.bind(this);
this.seekRecordPlayback = this._seekRecordPlayback.bind(this);
//chatApe
this.sendChatMsg = this._sendChatMsg.bind(this);
//videoApe
//this.getVideoPlayPath = this._getVideoPlayPath.bind(this);
this.getVideoPublishPath = this._getVideoPublishPath.bind(this);
this.getVideoAllChannelInfo = this._getVideoAllChannelInfo.bind(this);
this.publishVideo = this._publishVideo.bind(this);
this.stopPublishVideo = this._stopPublishVideo.bind(this);
this.sendVideoBroadcastMsg = this._sendVideoBroadcastMsg.bind(this);
//audioApe
//this.getAudioPlayPath = this._getPlayAudioPath.bind(this);
this.getAudioPublishPath = this._getPublishAudioPath.bind(this);
this.getAudioAllChannelInfo = this._getAudioAllChannelInfo.bind(this);
this.publishAudio = this._publishAudio.bind(this);
this.stopPublishAudio = this._stopPublishAudio.bind(this);
this.sendAudioBroadcastMsg = this.sendAudioCommandMsg.bind(this);
//whiteBoradApe
this.sendInsertAnnotaion = this._sendInsertAnnotaion.bind(this);
//this.sendDeleteAnnotaion=this._sendDeleteAnnotaion;
this.sendDeleteAllAnnotation = this._sendDeleteAllAnnotation.bind(this);
this.sendDeleteCurPageAnnotation = this._sendDeleteCurPageAnnotation.bind(this);
this.sendGotoPrev = this._sendGotoPrev.bind(this);
//DocApe
this.sendDocumentUpload = this._sendDocumentUpload.bind(this);//上传文档
this.sendDocumentSwitchDoc = this._sendDocumentSwitchDoc.bind(this); //切换文档
this.sendDocumentSwitchPage = this._sendDocumentSwitchPage.bind(this);//翻页
this.sendDocumentDelete = this._sassDeleteDocument.bind(this);
//删除文档,先通过Sass删除,sass删除成功之后再同步mcu
//this.sendDocumentDeleteAll= this._documentDeleteAll;//删除所有文档
this.sendDocumentCommand = this._sendDocumentCommand.bind(this);
//操作文档(翻页、缩放、滚动...)
this.getDocImageFullPath = this._getDocImageFullPath.bind(this);
//获取文档图片的完整路径
this.getDocPDFFullPath = this._getDocPDFFullPath.bind(this);//获取文档的完整路径
}
//mcu异常监听
_mcuErrorHandler(_data, _option) {
let option = _option || "";
let errorMessage = {"code": _data, "reson": MessageTypes.ErrorReson[_data] + " " + option};
loger.error("MCU_ERROR", errorMessage);
//DocApe
this.sendDocumentUpload = this._sendDocumentUpload.bind(this);;//上传文档
this.sendDocumentSwitchDoc = this._sendDocumentSwitchDoc.bind(this);; //切换文档
this.sendDocumentSwitchPage = this._sendDocumentSwitchPage.bind(this);;//翻页
this.sendDocumentDelete = this._sassDeleteDocument.bind(this);;//删除文档,先通过Sass删除,sass删除成功之后再同步mcu
//this.sendDocumentDeleteAll= this._documentDeleteAll;//删除所有文档
this.sendDocumentCommand = this._sendDocumentCommand.bind(this);;//操作文档(翻页、缩放、滚动...)
this.getDocImageFullPath=this._getDocImageFullPath.bind(this);;//获取文档图片的完整路径
this.getDocPDFFullPath=this._getDocPDFFullPath.bind(this);;//获取文档的完整路径
}
//mcu异常监听
_mcuErrorHandler(_data, _option) {
let option = _option || "";
let errorMessage = {"code": _data, "reson": MessageTypes.ErrorReson[_data] + " " + option};
loger.error("MCU_ERROR", errorMessage);
this._emit(MessageTypes.ERROR_EVENT,errorMessage);
/* if (_mcuErrorCallBackFun) {
_mcuErrorCallBackFun(errorMessage);
}*/
}
//获取当前的状态
_getMcuClientStatus() {
return GlobalConfig.getCurrentStatus();
}
//获取会议信息
_getClassDetail() {
return GlobalConfig.getClassDetail();
}
//获取当前会议的状态信息
_getClassStatusInfo(){
return GlobalConfig.classStatusInfo;
}
//关闭会议,所有人都退出
_doClassClose(_param) {
this._leaveClass();
}
//离开会议,断开连接
_doClassExit() {
this._leaveClass();
}
//当前的会议状态信息发生改变,需要保存会议状态到Sass
_onClassStatusInfoChange(_param) {
//如果MCU连接已经断开,不发送
if(GlobalConfig.getCurrentStatus().code!=GlobalConfig.statusCode_2.code){
loger.warn("不能保存会议状态",GlobalConfig.getCurrentStatus());
return;
}
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}
//当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;
//只有自己是主持人的时候出才处理下面的事情
if(_data!=null&&_data.nodeId!=null&&GlobalConfig.isHost){
loger.log("有人员离开,检查一下离开的人员是否关闭推流");
if(_video_ape){
_video_ape.stopPublishVideo(_data);
}
if(_audio_ape){
_audio_ape.stopPublishAudio(_data);
}
}
}
//当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
//的占用状态导致,对于这种情况,需要释放掉
_onClassNonentityRoster(_param){
if(_param==null||_param.nodeId==null){
loger.warn("onClassNonentityRoster.参数错误")
return;
}
let data={"nodeId":_param.nodeId};
if(_video_ape){
_video_ape.stopPublishVideo(data);
}
if(_audio_ape){
_audio_ape.stopPublishAudio(data);
}
}
//Sass
//初始化
_init(_param) {
//{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}
//判断传入的参数是否存在
if (_param == null || EngineUtils.isEmptyObject(_param)) {
loger.error('init初始化失败,参数错误');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);
return;
}
//判断必要的参数字段值
if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {
loger.error('init初始化失败', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);
return;
}
loger.log('init', _param);
//保存参数
GlobalConfig.classId = parseInt(_param.classId);
GlobalConfig.portal = _param.portal;
GlobalConfig.userRole = _param.userRole || ApeConsts.normal;
GlobalConfig.userId = _param.userId || "0";
GlobalConfig.userName=_param.userName || "";
//获取课堂校验信息
if (_sass) {
_sass.getJoinParams(GlobalConfig.getClassInfo());
}
}
//外部请求加入会议
_joinClass(_param) {
//_joinClassSuccessCallBackFun = _onSuccess;
//{"userName":"名字","password":""}
if (_param == null || EngineUtils.isEmptyObject(_param)) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
loger.log('不能进入会议,传递的参数不对.', _param);
return;
}
//判断userName
if (_param.userName == null || _param.userName == "") {
loger.log('不能进入会议,传递的参数不对.名字不能为空');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
return;
}
if(GlobalConfig.userName==null||GlobalConfig.userName==""){
GlobalConfig.userName = _param.userName;
}
GlobalConfig.password = _param.password || "";
GlobalConfig.hasCamera=(typeof _param.hasCamera=="boolean")? _param.hasCamera:false;
GlobalConfig.hasMicrophone=(typeof _param.hasMicrophone=="boolean")? _param.hasMicrophone:false;
//debugger;
//开始校验
if (_sass) {
_sass.passwordAndMd5Checking(GlobalConfig.getClassInfo());
}
}
// 用classId向SASS平台获取入会验证信息成功
_sassInitSuccessHandler(_data) {
//{"siteId":"h5test","passwordRequired":true,"md5":"de399d5540b3da2fbc1eb0a770d4fd66","code":0,"msType":1}
//储存数据
GlobalConfig.md5 = _data.md5 || "";//这个暂时用假数据,后台接口写完就有数据了
GlobalConfig.msType = _data.msType || 1;
GlobalConfig.siteId = _data.siteId || "";
GlobalConfig.classType = _data.meetingType || 0;
//host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
GlobalConfig.passwordRequired = _data.passwordRequired || false;//md5验证的时候需要Sass返回的值,不能更改
loger.log('SASS平台获取入会验证信息成功.');
//设置当前的会议状态
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_1);
//返回给客户端初始化成功的数据
let initSuccessCallBackData = {};
initSuccessCallBackData.siteId = GlobalConfig.siteId;
initSuccessCallBackData.classId = GlobalConfig.classId;
initSuccessCallBackData.userRole = GlobalConfig.userRole;
initSuccessCallBackData.userId = GlobalConfig.userId;
initSuccessCallBackData.classType = GlobalConfig.classType;
//host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
if (GlobalConfig.userRole== ApeConsts.host) {
initSuccessCallBackData.passwordRequired =true;
} else {
initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
}
this._emit(MessageTypes.CLASS_INIT_SUCCESS,initSuccessCallBackData);
/* if (_initSuccessCallBackFun) {
_initSuccessCallBackFun(initSuccessCallBackData);
}*/
}
// 通过SASS平台验证(密码和MD5)
_sassJoinSuccessHandler(_data) {
//返回值
/* flag 数值型 无 True:成功
Flag:失败
h5_mcu_list 字符串 H5muc列表
maxVideoChannels 数值型 最大视频路数
maxAudioChannels 数值型 最大音频路数
h5Module 数值型 H5开关
ms 字符串 Ms列表
mcu 字符串 Mcu列表
rs 字符串 Rs列表
doc 字符串 Doc列表*/
/* {
"record": "112.126.80.182:80",
"flag": "true",
"h5Module": 1,
"maxVideoChannels": 1,
"mcu": "123.56.73.119:7000;123.56.69.230:7000;112.126.80.182:7000",
"ms": "pubms.3mang.com:1935",
"doc": "101.200.150.192:80",
"rs": "pubms.3mang.com:1935",
"type": 1,
"maxAudioChannels": 1,
"h5_mcu_list": "123.56.73.119:7001;123.56.69.230:7001;112.126.80.182:7001"
}*/
/*
if (_data.h5_mcu_list) {
//MCU地址默认使用第一个
let server = _data.h5_mcu_list.split(";")[0];
GlobalConfig.MCUServerIP = server.split(":")[0];
GlobalConfig.MCUServerPort = server.split(":")[1];
}
//视频推流播流地址
if (_data.ms) {
//MS地址默认使用第一个
let server = _data.ms.split(";")[0];
GlobalConfig.MSServerIP = server.split(":")[0];
GlobalConfig.MSServerPort = server.split(":")[1];
}
//m3u8播流地址
if(_data.rs){
//RS地址默认使用第一个
let server = _data.rs.split(";")[0];
GlobalConfig.RSServerIP = server.split(":")[0];
GlobalConfig.RSServerPort = server.split(":")[1];
}
GlobalConfig.docServer = _data.doc;
GlobalConfig.h5_mcu_list = _data.h5_mcu_list;
GlobalConfig.h5Module = _data.h5Module;
GlobalConfig.mcu = _data.mcu;
GlobalConfig.ms = _data.ms;
GlobalConfig.record = _data.record;
GlobalConfig.rs = _data.rs;
GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
*/
/*
//这个接口获取的数据在getClassParam接口的数据中都有,内容重复,这个接口废弃
//获取会议基本信息
if (_sass) {
_sass.getClassDetail();
}
*/
//获取会议最完整的数据
if (_sass) {
_sass.getClassParam();
}
}
//获取会议基本信息getClassH5
_sassGetClassDetailSuccessHandler(_data) {
loger.log('获取getClassDetail完成.');
/* {
"cycle": 0,
"repeatmonthweekweek": 0,
"status": 1,
"repeatmonthday": 0,
"repeatmode": 0,
"beginTime": "2017-02-03 09:00:00",
"frequency": 1,
"endmode": 0,
"meetingContent": "",
"endTime": "2017-03-31 11:00:00",
"repeatweek": "",
"category": "",
"finalenddate": "",
"repeatday": 0,
"meetingName": "mcu1",
"errorCode": 0,
"monthType": 0,
"repeatmonthweekday": 0,
"endcount": 1
}*/
GlobalConfig.classDetail = _data;
GlobalConfig.className = _data.meetingName || "";
GlobalConfig.classBeginTime = _data.beginTime || "";
GlobalConfig.classEndTime = _data.endTime || "";
//获取会议所有信息和以前保存的会议状态信息(最全的信息)
if (_sass) {
_sass.getClassParam();
}
}
//获取会议所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do
_sassGetClassParamSuccessHandler(_data) {
//console.log(GlobalConfig.classStatusInfo)
loger.log('获取课堂会议的完整信息完成.');
// console.log(_data);
//包含整个会议最全的信息,储存数据
if (_data) {
GlobalConfig.className = _data.meetingName || "";
GlobalConfig.classBeginTime = _data.beginTime || "";
GlobalConfig.classEndTime = _data.endTime || "";
GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表
GlobalConfig.setRecordList(_data.recordList);//录制回放地址
GlobalConfig.setDocList(_data.docList);//文档地址
GlobalConfig.setMsList(_data.msList);//推流播流服务器地址
GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址
GlobalConfig.setMcuList(_data.mcuList);//mcu
GlobalConfig.setMusicList(_data.musicList);//
GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表
if (_data.mcuList) {
//MCU地址默认使用第一个
GlobalConfig.MCUServerIP =_data.mcuList[0].ip||"";
GlobalConfig.MCUServerPort =_data.mcuList[0].port||"";
}
//视频推流播流地址
if (_data.msList) {
//MS地址默认使用第一个
GlobalConfig.MSServerIP =_data.msList[0].ip||"";
GlobalConfig.MSServerPort =_data.msList[0].port||"";
}
//m3u8播流地址
if(_data.rsList){
//RS地址默认使用第一个
GlobalConfig.RSServerIP =_data.rsList[0].ip||"";
GlobalConfig.RSServerPort =_data.rsList[0].port||"";
}
//文档地址
if(_data.docList){
//doc地址默认使用第一个
GlobalConfig.DOCServerIP =_data.docList[0].ip||"";
GlobalConfig.DOCServerPort =_data.docList[0].port||"";
}
//record
if(_data.recordList){
//地址默认使用第一个
GlobalConfig.RecordServerIP =_data.recordList[0].ip||"";
GlobalConfig.RecordServerPort =_data.recordList[0].port||"";
}
}
if (_data.currentInfo) {
//根据从Sass获取的数据信息,同步最后一次保存的会议状态信息
loger.log("同步最后一次保存过的会议状态信息");
GlobalConfig.setClassStatusInfo(_data.currentInfo);
console.log(GlobalConfig.classStatusInfo);
} else {
loger.log("还没有保存过会议状信息");
}
//所有Sass流程完成,开始MCU连接
this._joinMCU();
}
//保存会议状态信息
_sassSaveClassStatusInfo() {
if (GlobalConfig.isHost) {
//只有加入会议之后才能保存数据
if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
//POST 保存数据
_sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo});//保存会议状态信息
} else {
loger.error("不能保存会议数据", GlobalConfig.getCurrentStatus());
}
} else {
loger.log("没有保存会议状态信息的权限 isHost", GlobalConfig.isHost);
}
}
//保存会态信息成功
_sassSaveClassStatusInfoSuccessHandler(_data) {
loger.log('保存会议状态信息成功.');
console.log(_data);
}
_sassSaveClassRecordInfoSuccessHandler(_data){
loger.log('保存会议录制信息成功.');
console.log(_data);
}
//Sass校验流程结束之后,开始加入MCU
_joinMCU() {
loger.log('加入底层MCU会议.');
if (_mcu) {
_mcu.joinMCU(GlobalConfig.getClassInfo());
}
}
// MCU 会议成功
_mcuJoinMCUClassSuccessHandler(_data) {
loger.log('MCU 会议成功.');
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
//返回给客户端初始化成功的数据
let initSuccessCallBackData = {};
initSuccessCallBackData.DOCServerIP =GlobalConfig.DOCServerIP;
initSuccessCallBackData.DOCServerPort =GlobalConfig.DOCServerPort;
initSuccessCallBackData.classId = GlobalConfig.classId;
initSuccessCallBackData.className = GlobalConfig.className;
initSuccessCallBackData.h5Module = GlobalConfig.h5Module;
initSuccessCallBackData.isHost = GlobalConfig.isHost;
initSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
initSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
initSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
initSuccessCallBackData.msType = GlobalConfig.msType;
initSuccessCallBackData.nodeId = GlobalConfig.nodeId;
initSuccessCallBackData.password = GlobalConfig.password;
initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
//GlobalConfig.passwordRequired 老师的默认是true
//GlobalConfig.portal=_data.portal;
initSuccessCallBackData.role = GlobalConfig.role;
initSuccessCallBackData.siteId = GlobalConfig.siteId;
initSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
initSuccessCallBackData.userId = GlobalConfig.userId;
initSuccessCallBackData.userName = GlobalConfig.userName;
initSuccessCallBackData.userRole = GlobalConfig.userRole;
initSuccessCallBackData.userType = GlobalConfig.userType;
initSuccessCallBackData.siteId = GlobalConfig.siteId;
initSuccessCallBackData.classId = GlobalConfig.classId;
initSuccessCallBackData.userRole = GlobalConfig.userRole;
initSuccessCallBackData.userId = GlobalConfig.userId;
initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
initSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
loger.log('加入会议成功');
console.log(initSuccessCallBackData);
//加入会议成功,广播消息
this._emit(MessageTypes.CLASS_JOIN_SUCCESS,initSuccessCallBackData);
/* //返回给客户数据
if (_joinClassSuccessCallBackFun) {
_joinClassSuccessCallBackFun(initSuccessCallBackData);
}*/
}
//Sass删除文档数据
_sassDeleteDocument(_param) {
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
//判断传入的参数是否存在
if (_param == null || EngineUtils.isEmptyObject(_param)) {
loger.error('sassDeleteDocument失败,参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);
return;
}
//判断必要的参数字段值
if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.docId == null || _param.docId == "") {
loger.error('sassDeleteDocument失败', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);
return;
}
loger.log('_sassDeleteDocument', _param);
if (_sass) {
_sass.sassDeleteDocument(_param);
}
}
//Sass删除文档成功之后,同步删除MCU数据
_sassDeleteDocumentSuccess(_param) {
loger.log('sassDeleteDocumentSuccess', _param);
this._sendDocumentDelete(_param);
}
//ConferApe
//开始上课
_sendStartClass(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_confer_ape){
_confer_ape.startClass(_param);
}
}
//暂停上课
_sendPauseClass(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_confer_ape){
_confer_ape.pauseClass(_param);
}
}
//停止上课
_sendCloseClass(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_confer_ape){
_confer_ape.closeClass(_param);
}
}
// 离开会议
_leaveClass() {
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
//停止推流
if(_video_ape){
_video_ape.stopPublishVideo();
this._emit(MessageTypes.ERROR_EVENT, errorMessage);
/* if (_mcuErrorCallBackFun) {
_mcuErrorCallBackFun(errorMessage);
}*/
}
//获取当前的状态
_getMcuClientStatus() {
return GlobalConfig.getCurrentStatus();
}
//获取课堂信息
_getClassDetail() {
return GlobalConfig.getClassDetail();
}
//获取当前课堂的状态信息
_getClassStatusInfo() {
return GlobalConfig.classStatusInfo;
}
//关闭课堂,所有人都退出
_doClassClose(_param) {
this._leaveClass();
}
//离开课堂,断开连接
_doClassExit() {
this._leaveClass();
}
//当前的课堂状态信息发生改变,需要保存课堂状态到Sass
_onClassStatusInfoChange(_param) {
//如果MCU连接已经断开,不发送
if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {
loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
return;
}
this._sassSaveClassStatusInfo();
}
//如果是第一次点击开始上课,需要创建录制时的文件名
_onClassRecordStart(_param) {
if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {
loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
return;
}
if (_sass) {
_sass.saveClassRecordContrlInfo(_param);
}
}
//有人员离开
_onClassDeleteRoster(_data) {
//在conferApe中做处理,这里不需要再处理
//{"nodeId":nodeId}
//当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;
/* if(_data!=null&&_data.nodeId!=null){
loger.log("有人员离开,检查一下离开的人员是否关闭推流");
if(_video_ape){
_video_ape.stopPublishVideo(_data);
}
if(_audio_ape){
_audio_ape.stopPublishAudio(_data);
}
}*/
}
//当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
//的占用状态导致,对于这种情况,需要释放掉
_onClassNonentityRoster(_param) {
if(GlobalConfig.isRecordPlayBack){
loger.warn("录制回放中,不处理")
return;
}
if (_param == null || _param.nodeId == null) {
loger.warn("onClassNonentityRoster.参数错误")
return;
}
let data = {"nodeId": _param.nodeId};
if (_video_ape) {
_video_ape.stopPublishVideo(data);
}
if (_audio_ape) {
_audio_ape.stopPublishAudio(data);
}
}
//Sass
//初始化
_init(_param) {
//{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}
//判断传入的参数是否存在
if (_param == null || EngineUtils.isEmptyObject(_param)) {
loger.error('init初始化失败,参数错误');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);
return;
}
//判断必要的参数字段值
if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {
loger.error('init初始化失败', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);
return;
}
loger.log('init', _param);
//保存参数
GlobalConfig.isRecordPlayBack=false;//设置为非录制回放状态
GlobalConfig.classId = parseInt(_param.classId);
GlobalConfig.portal = _param.portal;
GlobalConfig.userRole = _param.userRole || ApeConsts.normal;
GlobalConfig.userId = _param.userId || "0";
GlobalConfig.userName = _param.userName || "";
//最长允许录制的时间
if(_param.allowRecordMaxTime){
GlobalConfig.allowRecordMaxTime=parseInt(_param.allowRecordMaxTime);
}
//获取课堂校验信息
if (_sass) {
_sass.getJoinParams(GlobalConfig.getClassInfo());
}
}
//外部请求加入课堂
_joinClass(_param) {
//_joinClassSuccessCallBackFun = _onSuccess;
//{"userName":"名字","password":""}
if (_param == null || EngineUtils.isEmptyObject(_param)) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
loger.log('不能进入课堂,传递的参数不对.', _param);
return;
}
//判断userName
if (_param.userName == null || _param.userName == "") {
loger.log('不能进入课堂,传递的参数不对.名字不能为空');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
return;
}
if (GlobalConfig.userName == null || GlobalConfig.userName == "") {
GlobalConfig.userName = _param.userName;
}
GlobalConfig.autoLogin=_param.autoLogin||"";
GlobalConfig.password = _param.password || "";
GlobalConfig.hasCamera = (typeof _param.hasCamera == "boolean") ? _param.hasCamera : false;
GlobalConfig.hasMicrophone = (typeof _param.hasMicrophone == "boolean") ? _param.hasMicrophone : false;
loger.log("autoLoginMd5",GlobalConfig.classId,GlobalConfig.userId,GlobalConfig.userRole);
let autoLoginMd5=MD5(""+GlobalConfig.classId+GlobalConfig.userId+GlobalConfig.userRole);
loger.log("joinClass-GlobalConfig.autoLogin",GlobalConfig.autoLogin,"autoLoginMd5-",autoLoginMd5);
if(GlobalConfig.autoLogin&&autoLoginMd5==GlobalConfig.autoLogin){
// MD5(classId+userId+userRole)==m
//自动登录,跳过验证流程
loger.log("自动登录");
this._sassJoinSuccessHandler();
}else {
//不能自动登录,开始校验
if (_sass) {
_sass.passwordAndMd5Checking(GlobalConfig.getClassInfo());
}
}
}
// 用classId向SASS平台获取入会验证信息成功
_sassInitSuccessHandler(_data) {
//{"siteId":"h5test","passwordRequired":true,"md5":"de399d5540b3da2fbc1eb0a770d4fd66","code":0,"msType":1}
//储存数据
GlobalConfig.md5 = _data.md5 || "";//这个暂时用假数据,后台接口写完就有数据了
GlobalConfig.msType = _data.msType || 1;
GlobalConfig.siteId = _data.siteId || "";
GlobalConfig.classType = _data.meetingType || 0;
//host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
GlobalConfig.passwordRequired = _data.passwordRequired || false;//md5验证的时候需要Sass返回的值,不能更改
loger.log('SASS平台获取入会验证信息成功.');
//设置当前的课堂状态
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_1);
//返回给客户端初始化成功的数据
let initSuccessCallBackData = {};
initSuccessCallBackData.siteId = GlobalConfig.siteId;
initSuccessCallBackData.classId = GlobalConfig.classId;
initSuccessCallBackData.userRole = GlobalConfig.userRole;
initSuccessCallBackData.userId = GlobalConfig.userId;
initSuccessCallBackData.userName = GlobalConfig.userName;
initSuccessCallBackData.classType = GlobalConfig.classType;
//host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
if (GlobalConfig.userRole == ApeConsts.host) {
initSuccessCallBackData.passwordRequired = true;
} else {
initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
}
this._emit(MessageTypes.CLASS_INIT_SUCCESS, initSuccessCallBackData);
}
// 通过SASS平台验证(密码和MD5)
_sassJoinSuccessHandler(_data) {
//返回值
/* flag 数值型 无 True:成功
Flag:失败
h5_mcu_list 字符串 H5muc列表
maxVideoChannels 数值型 最大视频路数
maxAudioChannels 数值型 最大音频路数
h5Module 数值型 H5开关
ms 字符串 Ms列表
mcu 字符串 Mcu列表
rs 字符串 Rs列表
doc 字符串 Doc列表*/
//获取课堂最完整的数据
if (_sass) {
_sass.getClassParam();
}
}
//获取课堂所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do
_sassGetClassParamSuccessHandler(_data) {
//console.log(GlobalConfig.classStatusInfo)
loger.log('获取课堂课堂的完整信息完成.');
// console.log(_data);
//包含整个课堂最全的信息,储存数据
if (_data) {
GlobalConfig.mcuDelay = _data.mcuDelay || 60;//mcu消息延迟,用于文档模块
GlobalConfig.className = _data.meetingName || "";
GlobalConfig.classBeginTime = _data.beginTime || "";
GlobalConfig.classEndTime = _data.endTime || "";
GlobalConfig.userIp = _data.userIp || "";
GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表
GlobalConfig.setRecordList(_data.recordList);//录制回放地址
GlobalConfig.setDocList(_data.docList);//文档地址
GlobalConfig.setMsList(_data.msList);//推流播流服务器地址
GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址
GlobalConfig.setMcuList(_data.mcuList);//mcu
GlobalConfig.setMusicList(_data.musicList);//
GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表
if (_data.mcuList&&_data.mcuList.length>0) {
//MCU地址默认使用第一个
GlobalConfig.MCUServerIP = _data.mcuList[0].ip || "";
GlobalConfig.MCUServerPort = _data.mcuList[0].port || "";
}
//上课中视频推流播流地址
if (_data.msList&&_data.msList.length>0) {
//MS地址默认使用第一个
GlobalConfig.MSServerIP = _data.msList[0].ip || "";
GlobalConfig.MSServerPort = _data.msList[0].port || "";
}
//录制回放时m3u8播流地址
if (_data.rsList&&_data.rsList.length>0) {
//RS地址默认使用第一个
GlobalConfig.RSServerIP = _data.rsList[0].ip || "";
GlobalConfig.RSServerPort = _data.rsList[0].port || "";
}
//文档地址
if (_data.docList&&_data.docList.length>0) {
//doc地址默认使用第一个
GlobalConfig.DOCServerIP = _data.docList[0].ip || "";
GlobalConfig.DOCServerPort = _data.docList[0].port || "";
}
//record
if (_data.recordList&&_data.recordList.length>0) {
//地址默认使用第一个
GlobalConfig.RecordServerIP = _data.recordList[0].ip || "";
GlobalConfig.RecordServerPort = _data.recordList[0].port || "";
}
}
if (_data.currentInfo) {
//根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息
loger.log("本地同步最后一次保存过的课堂状态信息");
try {
GlobalConfig.setClassStatusInfo(JSON.parse(_data.currentInfo));
}catch (err){
GlobalConfig.setClassStatusInfo(_data.currentInfo);
}
loger.log(GlobalConfig.classStatusInfo);
} else {
loger.log("还没有保存过课堂状信息");
}
//录制回放不需要选点
if(GlobalConfig.isRecordPlayBack){
if (_parseBuf) {
//开启录制回放流程
loger.log("开启录制回放流程");
_parseBuf.readyRecordPlay();
}else {
loger.warn("开启录制回放流程失败,还未创建模块");
}
}else {
//根据用户的userIp获取信息
this.getUserIpInfo();
}
}
//根据UserIp获取ip信息
getUserIpInfo() {
if (_serverCheck) {
_serverCheck.getUserIpInfo("", GlobalConfig.userIp);
}
}
//MCU MS ip选点完成,开加入MCU
_serverCheckBestIpSuccessHandler(_data) {
loger.log("_serverCheckBestIpSuccessHandler,IP选点结束");
this._joinMCU();
}
//保存课堂状态信息
_sassSaveClassStatusInfo() {
if (GlobalConfig.isHost) {
//只有加入课堂之后才能保存数据
if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
//POST 保存数据
_sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo});//保存课堂状态信息
} else {
loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());
}
} else {
loger.log("没有保存课堂状态信息的权限 isHost", GlobalConfig.isHost);
}
}
//保存会态信息成功
_sassSaveClassStatusInfoSuccessHandler(_data) {
loger.log('保存课堂状态信息成功.');
loger.log(_data);
}
_sassSaveClassRecordInfoSuccessHandler(_data) {
loger.log('保存课堂录制信息成功.');
loger.log(_data);
}
//Sass校验流程结束之后,开始加入MCU
_joinMCU() {
loger.log('加入底层MCU课堂.');
if (_mcu) {
_mcu.joinMCU(GlobalConfig.getClassInfo());
}
}
// MCU 课堂成功
_mcuJoinMCUClassSuccessHandler(_data) {
loger.log('MCU 课堂成功.');
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
//返回给客户端初始化成功的数据
let joinClassSuccessCallBackData = {};
joinClassSuccessCallBackData.isRecordPlayBack=GlobalConfig.isRecordPlayBack;
joinClassSuccessCallBackData.DOCServerIP = GlobalConfig.DOCServerIP;
joinClassSuccessCallBackData.DOCServerPort = GlobalConfig.DOCServerPort;
joinClassSuccessCallBackData.classId = GlobalConfig.classId;
joinClassSuccessCallBackData.className = GlobalConfig.className;
joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;
joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;
joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
joinClassSuccessCallBackData.msType = GlobalConfig.msType;
joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;
joinClassSuccessCallBackData.password = GlobalConfig.password;
joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
//GlobalConfig.passwordRequired 老师的默认是true
//GlobalConfig.portal=_data.portal;
joinClassSuccessCallBackData.role = GlobalConfig.role;
joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
joinClassSuccessCallBackData.userId = GlobalConfig.userId;
joinClassSuccessCallBackData.userName = GlobalConfig.userName;
joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
joinClassSuccessCallBackData.userType = GlobalConfig.userType;
joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
joinClassSuccessCallBackData.classId = GlobalConfig.classId;
joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
joinClassSuccessCallBackData.userId = GlobalConfig.userId;
joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
joinClassSuccessCallBackData.country = GlobalConfig.country;//国家
joinClassSuccessCallBackData.city = GlobalConfig.city;//城市
joinClassSuccessCallBackData.province = GlobalConfig.province;//服务商
joinClassSuccessCallBackData.isp = GlobalConfig.isp;//服务商
joinClassSuccessCallBackData.classTimestamp=GlobalConfig.classTimestamp;//课堂进行的累积时间
joinClassSuccessCallBackData.recordPlaybackMaxTime=GlobalConfig.recordPlaybackMaxTime;//录制回放的总时间
loger.log('加入课堂成功');
loger.log(joinClassSuccessCallBackData);
//加入课堂成功,广播消息
this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);
}
//Sass删除文档数据
_sassDeleteDocument(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
//判断传入的参数是否存在
if (_param == null || EngineUtils.isEmptyObject(_param)) {
loger.error('sassDeleteDocument失败,参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);
return;
}
//判断必要的参数字段值
if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.docId == null || _param.docId == "") {
loger.error('sassDeleteDocument失败', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);
return;
}
loger.log('_sassDeleteDocument', _param);
if (_sass) {
_sass.sassDeleteDocument(_param);
}
}
//Sass删除文档成功之后,同步删除MCU数据
_sassDeleteDocumentSuccess(_param) {
loger.log('sassDeleteDocumentSuccess', _param);
this._sendDocumentDelete(_param);
}
//ConferApe
//开始上课
_sendStartClass(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_confer_ape) {
_confer_ape.startClass(_param);
}
}
//暂停上课
_sendPauseClass(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_confer_ape) {
_confer_ape.pauseClass(_param);
}
}
//停止上课
_sendCloseClass(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_confer_ape) {
_confer_ape.closeClass(_param);
}
}
// 离开课堂
_leaveClass() {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
//停止推流
if (_video_ape) {
_video_ape.stopPublishVideo();
}
if (_audio_ape) {
_audio_ape.stopPublishAudio();
}
//离开课堂
if (_confer_ape) {
_confer_ape.stopRecord();
_confer_ape.leaveClass();
}
//断开MCU连接
if (_mcu) {
_mcu.leaveMCU();
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3);
}
}
if(_audio_ape){
_audio_ape.stopPublishAudio();
//ChatApe
// 发送聊天消息
_sendChatMsg(_messageInfo) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_messageInfo === null || EngineUtils.isEmptyObject(_messageInfo)) {
loger.log('sendChatMsg 传递的参数不对', _messageInfo);
return;
}
if (_chat_ape) {
_chat_ape.sendChatMsg(_messageInfo);
}
}
//离开会议
if(_confer_ape){
_confer_ape.stopRecord();
_confer_ape.leaveClass();
//VidoeApe
videoUpdate(_data) {
//视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
if (_confer_ape) {
_confer_ape.updaterRosterStatus(_data);
}
}
//断开MCU连接
if(_mcu){
_mcu.leaveMCU();
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3);
_sendVideoBroadcastMsg(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_video_ape) {
return _video_ape.sendVideoBroadcastMsg(_param);
}
}
}
_getVideoPlayPath(_param) {
if (_video_ape) {
return _video_ape.getPlayVideoPath(_param);
}
}
//ChatApe
// 发送聊天消息
_sendChatMsg(_messageInfo) {
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
_getVideoPublishPath(_param) {
if (_video_ape) {
return _video_ape.getPublishVideoPath(_param);
}
}
if(_messageInfo===null||EngineUtils.isEmptyObject(_messageInfo)){
loger.log('sendChatMsg 传递的参数不对',_messageInfo);
return ;
_getVideoAllChannelInfo(_param) {
if (_video_ape) {
return _video_ape.getAllChannelInfo(_param);
}
}
if (_chat_ape) {
_chat_ape.sendChatMsg(_messageInfo);
_publishVideo(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_video_ape) {
return _video_ape.publishVideo(_param);
}
}
}
//VidoeApe
videoUpdate(_data){
//视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
if(_confer_ape){
_confer_ape.updaterRosterStatus(_data);
_stopPublishVideo(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_video_ape) {
return _video_ape.stopPublishVideo(_param);
}
}
}
_sendVideoBroadcastMsg(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
//AudioApe
audioUpdate(_data) {
//音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
if (_confer_ape) {
_confer_ape.updaterRosterStatus(_data);
}
}
if(_video_ape){
return _video_ape.sendVideoBroadcastMsg(_param);
sendAudioCommandMsg(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_audio_ape) {
return _audio_ape.sendAudioBroadcastMsg(_param);
}
}
_getPlayAudioPath(_param) {
if (_audio_ape) {
return _audio_ape.getAudioPlayPath(_param);
}
}
_getPublishAudioPath(_param) {
if (_audio_ape) {
return _audio_ape.getAudioPublishPath(_param);
}
}
_getAudioAllChannelInfo(_param) {
if (_audio_ape) {
return _audio_ape.getAllChannelInfo(_param);
}
}
}
_getVideoPlayPath(_param){
if(_video_ape){
return _video_ape.getPlayVideoPath(_param);
_publishAudio(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_audio_ape) {
return _audio_ape.publishAudio(_param);
}
}
}
_getVideoPublishPath(_param){
if(_video_ape){
return _video_ape.getPublishVideoPath(_param);
_stopPublishAudio(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_audio_ape) {
return _audio_ape.stopPublishAudio(_param);
}
}
}
_publishVideo(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
//WhiteBoardApe
// 添加标注,发送信息
_sendInsertAnnotaion(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_whiteboard_ape) {
_whiteboard_ape.sendInsetAnnotaion(_param);
}
}
//删除标注,发送信息
_sendDeleteAnnotaion(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_whiteboard_ape) {
_whiteboard_ape.sendDeleteAnnotaion(_param);
}
}
if(_video_ape){
return _video_ape.publishVideo(_param);
//删除当前页面上的所有标注
_sendDeleteCurPageAnnotation(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_whiteboard_ape) {
_whiteboard_ape.sendDeleteCurPageAnnotation(_param);
}
}
}
_stopPublishVideo(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
//删除所有标注
_sendDeleteAllAnnotation(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_whiteboard_ape) {
_whiteboard_ape.sendDeleteAllAnnotation(_param);
}
}
if(_video_ape){
return _video_ape.stopPublishVideo(_param);
//返回上一步标注
_sendGotoPrev(_param) {
if (_whiteboard_ape) {
_whiteboard_ape.sendGotoPrev(_param);
}
}
}
//AudioApe
audioUpdate(_data){
//音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
if(_confer_ape){
_confer_ape.updaterRosterStatus(_data);
//DocApe
//获取文档完整路径
_getDocImageFullPath(_param) {
if (_doc_ape) {
return _doc_ape.getDocImageFullPath(_param);
} else {
loger.error("文档模块还没有创建,无法获取");
return [];
}
}
}
sendAudioCommandMsg(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
_getDocPDFFullPath(_param) {
if (_doc_ape) {
return _doc_ape.getDocPDFFullPath(_param);
} else {
loger.error("文档模块还没有创建,无法获取");
return [];
}
}
if(_audio_ape){
return _audio_ape.sendAudioBroadcastMsg(_param);
//上传文档
_sendDocumentUpload(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_doc_ape) {
_doc_ape.documentUpload(_param);
}
}
}
_getPlayAudioPath(_param){
if(_audio_ape){
return _audio_ape.getAudioPlayPath(_param);
//切换文档
_sendDocumentSwitchDoc(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_doc_ape) {
_doc_ape.documentSwitchDoc(_param);
}
}
}
_getPublishAudioPath(_param){
if(_audio_ape){
return _audio_ape.getAudioPublishPath(_param);
//操作文档(翻页)
_sendDocumentSwitchPage(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_doc_ape) {
_doc_ape.documentSwitchPage(_param);
}
}
}
_publishAudio(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
//操作文档(缩放、滚动...)
_sendDocumentCommand(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_doc_ape) {
_doc_ape.documentCommand(_param);
}
}
if(_audio_ape){
return _audio_ape.publishAudio(_param);
//删除文档
_sendDocumentDelete(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_doc_ape) {
_doc_ape.documentDelete(_param);
}
}
}
_stopPublishAudio(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
//删除所有文档
_documentDeleteAll(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_doc_ape) {
_doc_ape.documentDeleteAll(_param);
}
}
if(_audio_ape){
return _audio_ape.stopPublishAudio(_param);
//// 文档变更,白板也需要做处理
docUpdateHandler(_data) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
loger.log('Doc UpdateId ->');
loger.log(_data);
if (_whiteboard_ape) {
_whiteboard_ape.docUpdateHandler(_data);
}
}
}
//文档删除,白板也需要做处理
docDeleteHandler(_data) {
if (_whiteboard_ape) {
_whiteboard_ape.docDeleteHandler(_data);
}
}
//WhiteBoardApe
// 添加标注,发送信息
_sendInsertAnnotaion(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
//文档加入频道成功,同步到MCU服务器上的数据
docJoinChannelSuccess() {
loger.log("docJoinChannelSuccess isHost=", GlobalConfig.isHost);
loger.log(GlobalConfig.docListPrepare);
loger.log("docJoinChannelSuccess docListPrepare=");
//如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传
if (GlobalConfig.isHost) {
for (let value of GlobalConfig.docListPrepare) {
if (value) {
/* //提前上传的文档文档信息的结构
{
"MD5": "f3feb3fac8cd3a953bded00e07a0c66b",
"absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
"createUserID": "972",
"createUserIP": "114.241.81.175",
"createUserName": "base",
"dynamicPPT": 0,
"dynamicTransferStatic": "",
"id": "8ab3b0ed5a00f2fa015a0219a3df016c",
"meetingNumber": "",
"name": "McuClient_v.1.0.1_API.pdf",
"orderStr": "",
"pdfSize": 5,
"processEndTime": "2017-02-03 11:54:31",
"processRate": 0,
"processStartTime": "2017-02-03 11:54:27",
"relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
"siteID": "h5test",
"size": 360920,
"status": 3,
"type": "pdf",
"uploadEndTime": "2017-02-03 11:54:27",
"uploadStartTime": "2017-02-03 11:54:27"
}*/
loger.log("判断是否需要把提前上传的文档上传到mcu", value);
let paramInfo = {
"pageNum": value.pdfSize,
"fileName": value.name,
"fileType": value.type,
"relativeUrl": value.relativeLocation,
"url": value.absoluteLocation,
"creatUserId": value.createUserID,
"docId": value.id,
"md5": value.MD5,
"visible": false
};
this._sendDocumentUpload(paramInfo);
}
}
}
}
if(_whiteboard_ape){
_whiteboard_ape.sendInsetAnnotaion(_param);
//录制回放相关的处理------------------------------------------------
//录制回放初始化
_initRecordPlayback(_param){
//{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}
if (_param == null) {
loger.error('录制回放初始化失败,参数错误');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED);
return;
}
//判断必要的参数字段值
if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {
loger.error('录制回放初始化失败', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED);
return;
}
loger.log('录制回放', _param);
//保存参数
GlobalConfig.isRecordPlayBack=true;//设置为录制回放状态
GlobalConfig.classId = parseInt(_param.classId);
GlobalConfig.portal = _param.portal;
GlobalConfig.userRole =ApeConsts.normal;//*************很重要,录制回放的时候,身份模式是普通人********
GlobalConfig.userId = _param.userId || "0";
GlobalConfig.userName = _param.userName || "";
//获取课堂最完整的数据,录制回放需要获取课堂数据
if (_sass) {
_sass.getClassParam();
}
}
}
//删除标注,发送信息
_sendDeleteAnnotaion(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
//开始录制回放
_startRecordPlayback(_param) {
if (_parseBuf) {
_parseBuf.startRecordPlayback(_param);
}
}
if(_whiteboard_ape){
_whiteboard_ape.sendDeleteAnnotaion(_param);
//停止录制回放
_stopRecordPlayback(_param) {
if (_parseBuf) {
_parseBuf.stopRecordPlayback(_param);
}
}
//暂停录制回放
_pauseRecordPlayback(_param) {
if (_parseBuf) {
_parseBuf.pauseRecordPlayback(_param);
}
}
}
//删除当前页面上的所有标注
_sendDeleteCurPageAnnotation(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_whiteboard_ape){
_whiteboard_ape.sendDeleteCurPageAnnotation(_param);
}
}
//删除所有标注
_sendDeleteAllAnnotation(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_whiteboard_ape){
_whiteboard_ape.sendDeleteAllAnnotation(_param);
}
}
//返回上一步标注
_sendGotoPrev(_param){
if(_whiteboard_ape){
_whiteboard_ape.sendGotoPrev(_param);
}
}
//DocApe
//获取文档完整路径
_getDocImageFullPath(_param){
if(_doc_ape){
return _doc_ape.getDocImageFullPath(_param);
}else {
loger.error("文档模块还没有创建,无法获取");
return [];
}
}
_getDocPDFFullPath(_param){
if(_doc_ape){
return _doc_ape.getDocPDFFullPath(_param);
}else {
loger.error("文档模块还没有创建,无法获取");
return [];
}
}
//上传文档
_sendDocumentUpload(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_doc_ape){
_doc_ape.documentUpload(_param);
}
}
//切换文档
_sendDocumentSwitchDoc(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_doc_ape){
_doc_ape.documentSwitchDoc(_param);
}
}
//操作文档(翻页)
_sendDocumentSwitchPage(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_doc_ape){
_doc_ape.documentSwitchPage(_param);
}
}
//操作文档(缩放、滚动...)
_sendDocumentCommand(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_doc_ape){
_doc_ape.documentCommand(_param);
}
}
//删除文档
_sendDocumentDelete(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_doc_ape){
_doc_ape.documentDelete(_param);
}
}
//删除所有文档
_documentDeleteAll(_param){
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(_doc_ape){
_doc_ape.documentDeleteAll(_param);
}
}
//// 文档变更,白板也需要做处理
docUpdateHandler(_data) {
if(!_mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
loger.log('Doc UpdateId ->');
console.log(_data);
if(_whiteboard_ape){
_whiteboard_ape.docUpdateHandler(_data);
}
}
//文档删除,白板也需要做处理
docDeleteHandler(_data){
if(_whiteboard_ape){
_whiteboard_ape.docDeleteHandler(_data);
}
}
//文档加入频道成功,同步到MCU服务器上的数据
docJoinChannelSuccess(){
loger.log("docJoinChannelSuccess isHost=",GlobalConfig.isHost);
console.log(GlobalConfig.docListPrepare);
loger.log("docJoinChannelSuccess docListPrepare=");
//如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传
if(GlobalConfig.isHost){
for (let value of GlobalConfig.docListPrepare){
if(value){
/* //提前上传的文档文档信息的结构
{
"MD5": "f3feb3fac8cd3a953bded00e07a0c66b",
"absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
"createUserID": "972",
"createUserIP": "114.241.81.175",
"createUserName": "base",
"dynamicPPT": 0,
"dynamicTransferStatic": "",
"id": "8ab3b0ed5a00f2fa015a0219a3df016c",
"meetingNumber": "",
"name": "McuClient_v.1.0.1_API.pdf",
"orderStr": "",
"pdfSize": 5,
"processEndTime": "2017-02-03 11:54:31",
"processRate": 0,
"processStartTime": "2017-02-03 11:54:27",
"relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
"siteID": "h5test",
"size": 360920,
"status": 3,
"type": "pdf",
"uploadEndTime": "2017-02-03 11:54:27",
"uploadStartTime": "2017-02-03 11:54:27"
}*/
loger.log("判断是否需要把提前上传的文档上传到mcu",value);
let paramInfo={
"pageNum": value.pdfSize,
"fileName": value.name,
"fileType": value.type,
"relativeUrl": value.relativeLocation,
"url": value.absoluteLocation,
"creatUserId":value.createUserID,
"docId": value.id,
"md5":value.MD5,
"visible": false
};
this._sendDocumentUpload(paramInfo);
}
}
}
}
//seek录制回放
_seekRecordPlayback(_param) {
if (_parseBuf) {
_parseBuf.seekRecordPlayback(_param);
}
}
//录制回放加入 课堂成功
_joinRecordPlaybackSuccessHandler(_data) {
loger.log('加入录制回放成功.');
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
//返回给客户端初始化成功的数据
let joinClassSuccessCallBackData = {};
joinClassSuccessCallBackData.isRecordPlayBack=GlobalConfig.isRecordPlayBack;
joinClassSuccessCallBackData.DOCServerIP = GlobalConfig.DOCServerIP;
joinClassSuccessCallBackData.DOCServerPort = GlobalConfig.DOCServerPort;
joinClassSuccessCallBackData.classId = GlobalConfig.classId;
joinClassSuccessCallBackData.className = GlobalConfig.className;
joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;
joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;//
joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
joinClassSuccessCallBackData.msType = GlobalConfig.msType;
joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;
joinClassSuccessCallBackData.password = GlobalConfig.password;
joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
//GlobalConfig.passwordRequired 老师的默认是true
//GlobalConfig.portal=_data.portal;
joinClassSuccessCallBackData.role = GlobalConfig.role;
joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
joinClassSuccessCallBackData.userId = GlobalConfig.userId;
joinClassSuccessCallBackData.userName = GlobalConfig.userName;
joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
joinClassSuccessCallBackData.userType = GlobalConfig.userType;
joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
joinClassSuccessCallBackData.classId = GlobalConfig.classId;
joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
joinClassSuccessCallBackData.userId = GlobalConfig.userId;
joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
joinClassSuccessCallBackData.country = GlobalConfig.country;//国家
joinClassSuccessCallBackData.city = GlobalConfig.city;//城市
joinClassSuccessCallBackData.province = GlobalConfig.province;//服务商
joinClassSuccessCallBackData.isp = GlobalConfig.isp;//服务商
joinClassSuccessCallBackData.classTimestamp=GlobalConfig.classTimestamp;//课堂进行的累积时间
joinClassSuccessCallBackData.recordPlaybackMaxTime=GlobalConfig.recordPlaybackMaxTime;//录制回放的总时间
loger.log(joinClassSuccessCallBackData);
//和加入课堂成功使用同样的消息处理
this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);
}
}
... ...
... ... @@ -85,11 +85,13 @@ class EverSocket extends Emiter {
loger.log('WebSocket,Timers销毁');
window.clearInterval(this.pingTimer);
window.clearInterval(this.pongTimer);
window.clearInterval(this.reConnectionTimeout);
this._setConnected(false);//先设置状态
this._enableEverSocket = false;
if(this.websocket==null){
loger.log('WebSocket,Timers已经销毁');
return;
}
this._setConnected(false);//先设置状态
this.websocket.onopen = undefined;
this.websocket.onclose = undefined;
this.websocket.onerror = undefined;
... ... @@ -100,7 +102,7 @@ class EverSocket extends Emiter {
loger.log('ignore errors');
}
this.websocket = undefined;
this._enableEverSocket = false;
}
_onOpen() {
... ...
... ... @@ -70,6 +70,7 @@ class GlobalConfig {
classStatusInfo.classStartTime=this.classStartTime;//课堂点击开始时间
classStatusInfo.classStopTime=this.classStopTime;//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
classStatusInfo.classTimestamp=this.classTimestamp;//相对于点开始课堂的时间戳
classStatusInfo.recordPlaybackMaxTime=this.recordPlaybackMaxTime;//相对于点开始课堂的时间戳
classStatusInfo.classBeginTime=this.classBeginTime;//课堂创建的时间,这个是Sass返回的
classStatusInfo.classEndTime=this.classEndTime;//课堂结束的时间,这个是Sass返回的
... ... @@ -234,14 +235,14 @@ class GlobalConfig {
}
GlobalConfig.statusCode_0={"code":0,message:"SDK 未初始化"};
GlobalConfig.statusCode_1={"code":1,message:"未加入会议"};
GlobalConfig.statusCode_2={"code":2,message:"已经加入会议"};
GlobalConfig.statusCode_3={"code":3,message:"已经离开会议"};
GlobalConfig.statusCode_1={"code":1,message:"未加入课堂"};
GlobalConfig.statusCode_2={"code":2,message:"已经加入课堂"};
GlobalConfig.statusCode_3={"code":3,message:"已经离开课堂"};
GlobalConfig.statusCode_4={"code":4,message:"未知状态"};
GlobalConfig.md5="";
GlobalConfig.msType=1;//目前固定用这个
GlobalConfig.mcuDelay=3000;//默认的延迟时间
GlobalConfig.mcuDelay=60;//默认的延迟时间 flash中使用的是3000毫秒
GlobalConfig.docDelay=1600;//文档模块加入成功之后延迟发送送成功的消息给主模块
GlobalConfig.portal="112.126.80.182:80";//Sass IP
... ... @@ -272,7 +273,7 @@ GlobalConfig.hasCamera=false;//摄像头是否可用
GlobalConfig.hasMicrophone=false;//麦克风是否可用
GlobalConfig.deviceType=0; //设备类型 0:电脑 1:安卓 2:ios
GlobalConfig.userIP="";//用户当前IP
GlobalConfig.userIp="";//用户当前IP
GlobalConfig.userId=0;
GlobalConfig.userName="";
... ... @@ -297,13 +298,14 @@ GlobalConfig.classBeginTime="";//课堂创建的时间,这个是Sass返回的
GlobalConfig.classEndTime="";//课堂结束的时间,这个是Sass返回的
GlobalConfig.classTimestamp=0;//从课堂开始到现在的时
GlobalConfig.recordPlaybackMaxTime=0;//录制回放的总时间
GlobalConfig.recordStatus=false;//当前录制状态
GlobalConfig.recordTimestamp=0;//相对于首次开始录制的进行时间
GlobalConfig.recordFileName="";//录制的文件名,如 果为空就创建一个
GlobalConfig.recordDownloadUrl="";//下载地址
GlobalConfig.recordReplaytickValues={}; // 滚动条关键点,用于快进快退
GlobalConfig.updateClassInfoDelay=30;//(秒),每隔30秒同步一次会议状态的并保存到Sass
GlobalConfig.updateClassInfoDelay=30;//(秒),每隔30秒同步一次课堂状态的并保存到Sass
//GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get set 获取
... ... @@ -313,7 +315,7 @@ GlobalConfig.activeDocCurPage=1;//当前激活的文档的当前页
GlobalConfig.classAllParam={};//Sass直接返回的所有会议信息(最全)
GlobalConfig.classAllParam={};//Sass直接返回的所有课堂信息(最全)
GlobalConfig.classDetail={};//Sass直接返回的当前课堂基本信息
GlobalConfig.docListPrepare=[]; // 已经提前上传的文档,进入课堂后需要自动加载
... ... @@ -323,7 +325,14 @@ GlobalConfig.mcuList=[];//录制服务器地址集合
GlobalConfig.msList=[];//ms服务器地址集合
GlobalConfig.musicList=[];//music服务器地址集合
GlobalConfig.musicListPrepare=[];//提提前上传的music集合
GlobalConfig.rsList=[];
GlobalConfig.rsList=[];//录制回放中视频点播地址
GlobalConfig.country ="";//国家
GlobalConfig.city ="";//城市
GlobalConfig.province = "";//服务商
GlobalConfig.isp ="";//服务商
GlobalConfig.isRecordPlayBack=false;//是否是录制回放,默认是否
GlobalConfig.allowRecordMaxTime=14400;//(秒)允许录制的最长时间,默认是4小时
export default GlobalConfig;
... ...
... ... @@ -9,11 +9,11 @@ function MessageTypes() {}
MessageTypes.CLASS_INIT_SUCCESS="class_init_success";//'class.init.success';//初始化成功
//MessageTypes.CLASS_INIT_FAILED='class.init.failed';//初始化失败
//加入会议相关事件定义
//加入课堂相关事件定义
MessageTypes.CLASS_JOIN_MCU_SUCCESS ="class_join_mcu_success"// 'join.mcu.success';
//MessageTypes.CLASS_JOIN_FAILED = 'join.class.failed';
//会议信息和操作事件定义
//课堂信息和操作事件定义
//MessageTypes.CLASS_SHOW_DETAIL = 'class_detail.message';
MessageTypes.CLASS_JOIN_SUCCESS ="class_join_success"// 'join.class.success';
MessageTypes.CLASS_UPDATE_ROSTER_NUM ="class_update_roster_num";// 'roster_num.message';
... ... @@ -21,9 +21,9 @@ MessageTypes.CLASS_INSERT_ROSTER ="class_insert_roster";// 'roster.insert.messag
MessageTypes.CLASS_DELETE_ROSTER ="class_delete_roster"// 'roster.delete.message';
MessageTypes.CLASS_NONENTITY_ROSTER ="class_nonenetity_roster";// 'roster.nonentity.message';
MessageTypes.CLASS_EXIT ="class_exit";// 'class.exit';//退出 关闭会议
MessageTypes.CLASS_UPTATE_STATUS ="class_update_status";// 'class.update.status';//更新会议状态信息
MessageTypes.CLASS_STATUS_INFO_CHANGE="class_status_info_change";// 'class.status.info.change';//会议状态信息发生改变,需要保存数据到sass和同步MCU
MessageTypes.CLASS_EXIT ="class_exit";// 'class.exit';//退出 关闭课堂
MessageTypes.CLASS_UPTATE_STATUS ="class_update_status";// 'class.update.status';//更新课堂状态信息
MessageTypes.CLASS_STATUS_INFO_CHANGE="class_status_info_change";// 'class.status.info.change';//课堂状态信息发生改变,需要保存数据到sass和同步MCU
MessageTypes.CLASS_UPDATE_TIMER="class_update_timer";//'class.update.timer';//更新当前上课的时间
... ... @@ -37,13 +37,13 @@ MessageTypes.CHAT_RECEIVE ="chat_receive_message";// 'chat.receive';
//视频模块事件定义
MessageTypes.VIDEO_PLAY ="video_play";// 'video.play';//播放视频
MessageTypes.VIDEO_STOP ="video_stop"; //'video.stop';//停止视频
//MessageTypes.VIDEO_UPDATE ="video.update";// 'video.update';//废弃,400、401取代
MessageTypes.VIDEO_UPDATE ="video_update";// //这个监听事件不能删除,需要通知课堂模块,检查channel占用(内部使用)
MessageTypes.VIDEO_BROADCAST= "video_broadcast";//'video.broadcast';
//音频模块事件定义
MessageTypes.AUDIO_PLAY ="audio_play";// 'audio.play';//播放
MessageTypes.AUDIO_STOP = "audio_stop";//'audio.stop';//停止
//MessageTypes.AUDIO_UPDATE = "502";//'audio.update';
MessageTypes.AUDIO_UPDATE = "audio_update";//这个监听事件不能删除,需要通知课堂模块,检查channel占用(内部使用)
MessageTypes.AUDIO_BROADCAST= "audio_broadcast";//'audio.broadcast';
... ... @@ -57,8 +57,6 @@ MessageTypes.DOC_UPDATE ="document_update";// 'document.update';//更新文档(
//MessageTypes.DOC_DELETE='document.delete';//删除文档
//MessageTypes.DOC_ANNOTATION = 'document.annotation';//笔记
//白板笔记事件定义
MessageTypes.WHITEBOARD_ANNOTATION_UPDATE ="whiteboard_annotation_update";// 'whiteboard.annotation.update';
//MessageTypes.WHITEBOARD_ANNOTAION_INSERT = 'whiteboard.annotation.insert';
... ... @@ -66,6 +64,9 @@ MessageTypes.WHITEBOARD_ANNOTATION_UPDATE ="whiteboard_annotation_update";// 'wh
//MessageTypes.WHITEBOARD_ANNOTATION_CLEAR = 'whiteboard.annotation.clear';
//录制回放
MessageTypes.RECORD_PLAYBACK_UPDATE ="record_playback_update";//录制回放更新信息
//错误事件定义
MessageTypes.MCU_ERROR ="mcu_error";//"mcuError";//MCU错误(内部使用)
MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使用)
... ... @@ -73,7 +74,7 @@ MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使
//---------------错误消息 ErrorCode 定义-------------------------------------------------
//会议初始化失败的几种情况
//课堂初始化失败的几种情况
MessageTypes.ERR_CLASS_INIT_PARAM=100;//初始化参数错误
MessageTypes.ERR_CLASS_INIT_NETWORK=101;//初始化网络错误
MessageTypes.ERR_CLASS_INIT_PROTOCOL=102;//初始化协议错误
... ... @@ -83,22 +84,22 @@ MessageTypes.ERR_CLASS_INIT_FAILED_2=105;//初始化验证失败,无效的课堂
MessageTypes.ERR_CLASS_INIT_FAILED_3=106;//初始化验证失败,没有对应的站点
MessageTypes.ERR_CLASS_INIT_FAILED_4=107;//初始化验证失败,站点已过期
//加入会议失败的几种情况
MessageTypes.ERR_CLASS_JOIN_NETWORK=200;//加入会议网络错误
MessageTypes.ERR_CLASS_JOIN_PROTOCOL=201;//加入会议化协议错误
MessageTypes.ERR_CLASS_JOIN_FAILED=202;//加入会议化异常错误
MessageTypes.ERR_CLASS_JOIN_PARAM=203;//加入会议参数错误
//加入课堂失败的几种情况
MessageTypes.ERR_CLASS_JOIN_NETWORK=200;//加入课堂网络错误
MessageTypes.ERR_CLASS_JOIN_PROTOCOL=201;//加入课堂化协议错误
MessageTypes.ERR_CLASS_JOIN_FAILED=202;//加入课堂化异常错误
MessageTypes.ERR_CLASS_JOIN_PARAM=203;//加入课堂参数错误
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失败
//APE
MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN=500;//APE在sdk为初始化或未加入会议之前调用发送数据接口
MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN=500;//APE在sdk为初始化或未加入课堂之前调用发送数据接口
MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG=501;//APE在接口调用时参数错误
//DOC
... ... @@ -110,10 +111,15 @@ MessageTypes.ERR_SDK_FAILED=700;// sdk还没初始化
MessageTypes.ERR_INTERFACE_NONE=701;//调用的接口不存在
MessageTypes.ERR_INTERFACE_PARAMS_ERROR=702;//调用的接口,传递的参数不正确
MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED=910;//初始化录制回放失败
MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED=911;//获取录制回放数据失败
MessageTypes.ERR_NETWORK=10000;//网络错误
MessageTypes.ERR_UNKNOWN=10001;//未知错误
MessageTypes.ERR_SOCKET_DISCONNECT=20000;//MCU断开连接,已经离开会议
MessageTypes.ERR_SOCKET_DISCONNECT=20000;//MCU断开连接,已经离开课堂
//---------------错误消息 Error Reson 定义-------------------------------------------------
MessageTypes.ErrorReson={};
... ... @@ -128,22 +134,23 @@ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_3]="初始化验证
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_4]="初始化验证失败,站点已过期";
//加入会议失败的几种情况
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_NETWORK]="加入会议网络错误";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PROTOCOL]="加入会议化协议错误";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FAILED]="加入会议化异常错误";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PARAM]="加入会议参数错误";
//加入课堂失败的几种情况
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_NETWORK]="加入课堂网络错误";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PROTOCOL]="加入课堂化协议错误";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FAILED]="加入课堂化异常错误";
MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PARAM]="加入课堂参数错误";
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失败";
MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_PARAML]="获取ClassParam失败";
//APE
MessageTypes.ErrorReson[MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN]="APE在sdk为初始化或未加入会议之前调用发送数据接口";
MessageTypes.ErrorReson[MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN]="APE在sdk为初始化或未加入课堂之前调用发送数据接口";
MessageTypes.ErrorReson[MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG]="APE在接口调用时参数错误";
//DOC
... ... @@ -154,10 +161,16 @@ MessageTypes.ErrorReson[MessageTypes.ERR_SDK_FAILED]="sdk还没初始化";
MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_NONE]="调用的接口不存在";
MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_PARAMS_ERROR]="调用的接口,传递的参数不正确";
MessageTypes.ErrorReson[MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED]="初始化录制回放失败";
MessageTypes.ErrorReson[MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED]="获取录制回放数据失败";
MessageTypes.ErrorReson[MessageTypes.ERR_NETWORK]="网络错误";
MessageTypes.ErrorReson[MessageTypes.ERR_UNKNOWN]="未知错误";
MessageTypes.ErrorReson[MessageTypes.ERR_SOCKET_DISCONNECT]="MCU断开连接,已经离开会议";
MessageTypes.ErrorReson[MessageTypes.ERR_SOCKET_DISCONNECT]="MCU断开连接,已经离开课堂";
... ...
import ByteBuffer from 'libs/bytebuffer.min';
import Emiter from 'Emiter';
import MessageTypes from 'MessageTypes';
import Loger from 'Loger';
import pdu from 'pdus/index';
import PduType from 'pdus/PduType';
import PduConsts from 'pdus/PduConsts';
import ApeConsts from 'apes/ApeConsts';
import ArrayBufferUtil from 'libs/ArrayBufferUtil';
import Base64 from 'base64-js';
import GlobalConfig from 'GlobalConfig';
import EngineUtils from 'EngineUtils';
import TimerCounter from "TimerCounter";
let parseBuffer;
// 日志对象
const loger = Loger.getLoger('RecordPlayBackParse');
const Default = 0;//未开始
const PLAY = 1;//播放中
const PAUSE = 2;//暂停
const SEEK = 3;//seek
const STOP = 4;//停止
class RecordPlayBackParse extends Emiter {
constructor() {
super();
loger.log("RecordPlayBackParse");
parseBuffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
parseBuffer.clear();
//console.log(parseBuffer);
this._recordPlaybackTimestamp = 0;//回放的时间
this._recordPlaybackMaxTime = 0;//录制回放的总时间
this._isReady = false;//录制回放是否已经准备完成
this._apes = {};
//this._messages = {};
this._conferApeMssages = {};//会议数据
this._chatApeMssages = {};//聊天数据
this._videoApeMssages = {};//视频数据
this._audioApeMssages = {};//音频数据
this._docApeMssages = {};//文档数据
this._whiteApeMssages = {};//白板数据
this._timerCounter = new TimerCounter();//计时器
this._timerCounter.addTimerCallBack(this._timerCounterUptate.bind(this), 1);
}
//method--------------------内部---------------------------------------------
// 注册Ape
registerApe(ape) {
this._apes[ape._session_id] = ape;
}
initReplay() {
this._stopTimerCounter();
this._recordPlaybackTimestamp = 0;//回放的时间
this._recordPlaybackMaxTime = 0;//录制回放的总时间
this._isReady = false;//录制回放是否已经准备完成
this._conferApeMssages = {};//会议数据
this._chatApeMssages = {};//聊天数据
this._videoApeMssages = {};//视频数据
this._audioApeMssages = {};//音频数据
this._docApeMssages = {};//文档数据
this._whiteApeMssages = {};//白板数据
}
//发送数据个各个APE模块处理,data是数据,seekTime是当前数据需要seek的时间长度(针对音视频的seek)
_everSocketMsgReceivedHandler(data, seekTime) {
let pduMsg = pdu.decode_pdu(data);
let pduType = pduMsg.get("type");
let pduData = pduMsg.get("data");
//*************非常重要******************
//客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端,
//所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的
if (pduType == PduType.RCPDU_UNIFORM_SEND_DATA_REQUEST) {
pduMsg.type = PduType.RCPDU_SEND_DATA_REQUEST;
pduType = PduType.RCPDU_SEND_DATA_REQUEST;
}
loger.log('_everSocketMsgReceivedHandler->pduType', pduType, "seekTime->", seekTime);
switch (pduType) {
case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
//加入课堂请求返回数据处理
let joinConfPdu = pdu['RCConferenceJoinResponsePdu'].decode(pduData);
let pduResultCode = joinConfPdu.result;
loger.warn('RCPDU_CONNECT_PROVIDER_RESPONSE ->pduResultCode:' + pduResultCode);
switch (pduResultCode) {
case PduConsts.RET_SUCCESS:
//加入成功
//this._updateMCUConfInfoDescription(joinConfPdu.classDescription);
this._emit(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this.classInfo);
break;
case PduConsts.RET_FULL_CAPACITY:
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FULL);
break;
default:
loger.warn('JoinConfPdu-未知类型-等待处理.', pduResultCode);
break
}
break;
case PduType.RCPDU_SEND_DATA_REQUEST:
//先判断当前消息属于哪个APE 根据 sessionId来判断
let ape = this._apes[pduMsg.sessionId];
let sessionLabel = ApeConsts(pduMsg.sessionId);
//对方发送消息
if (ape) {
let subTypeLabel = pdu.id2type(pduMsg.subType);
//loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType);
//ape广播事件,只要ape中监听就能收到
ape._emit(pduMsg.subType, pduMsg.data, seekTime);//seekTime是音视频模块seek的时间长度
} else {
loger.warn(sessionLabel + '尚未注册');
}
break;
default:
loger.warn('PDU-未知类型-等待处理.', pduType);
}
}
//解析和储存,录制回放EverSocket底层消息处理 data-数据;timestamp-数据对应的时间戳
_parseSaveSocketMsgReceivedHandler(data, timestamp) {
let pduMsg = pdu.decode_pdu(data);
let pduType = pduMsg.get("type");
let pduData = pduMsg.get("data");
//*************非常重要******************
//客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端,
//所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的
if (pduType == PduType.RCPDU_UNIFORM_SEND_DATA_REQUEST) {
pduMsg.type = PduType.RCPDU_SEND_DATA_REQUEST;
pduType = PduType.RCPDU_SEND_DATA_REQUEST;
}
loger.log('pduType', pduType);
switch (pduType) {
case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
//加入课堂请求返回数据处理
let joinConfPdu = pdu['RCConferenceJoinResponsePdu'].decode(pduData);
let pduResultCode = joinConfPdu.result;
loger.warn('RCPDU_CONNECT_PROVIDER_RESPONSE ->pduResultCode:' + pduResultCode);
switch (pduResultCode) {
case PduConsts.RET_SUCCESS:
//加入成功
//this._updateMCUConfInfoDescription(joinConfPdu.classDescription);
this._emit(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this.classInfo);
break;
case PduConsts.RET_FULL_CAPACITY:
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FULL);
break;
default:
loger.warn('JoinConfPdu-未知类型-等待处理.', pduResultCode);
break
}
break;
case PduType.RCPDU_SEND_DATA_REQUEST:
//先判断当前消息属于哪个APE 根据 sessionId来判断
let ape = this._apes[pduMsg.sessionId];
let sessionLabel = ApeConsts(pduMsg.sessionId);
//只做解析存储,不对外发送
loger.log('解析数据-timestamp->', timestamp, 'sessionId->', pduMsg.sessionId, 'sessionLabel->', sessionLabel);
switch (pduMsg.sessionId) {
case ApeConsts.CONFERENCE_SESSION_ID:
this.saveParseData(data, timestamp, this._conferApeMssages);
break;
case ApeConsts.CHAT_SESSION_ID:
this.saveParseData(data, timestamp, this._chatApeMssages);
break;
case ApeConsts.DOCSHARING_SESSION_ID:
this.saveParseData(data, timestamp, this._docApeMssages);
break;
case ApeConsts.WHITEBOARD_SESSION_ID:
this.saveParseData(data, timestamp, this._whiteApeMssages);
break;
case ApeConsts.VIDEO_SESSION_ID:
this.saveParseData(data, timestamp, this._videoApeMssages);
break;
case ApeConsts.AUDIO_SESSION_ID:
this.saveParseData(data, timestamp, this._audioApeMssages);
break;
default:
break;
}
break;
default:
loger.warn('PDU-未知类型-等待处理.', pduType);
}
}
//保存数据
saveParseData(data, timestamp, apeMessages) {
let messageItem = apeMessages[timestamp];
if (!messageItem) {
apeMessages[timestamp] = [];//数组存数据,因为有1秒内收到多个消息的情况,timestamp是按秒记录的
messageItem = apeMessages[timestamp];
}
messageItem.push({"timestamp": timestamp, "byteData": data});
}
//开启计时器
_startTimerCounter() {
if (this._timerCounter) {
this._timerCounter.startTimer();
}
}
//停止计时器
_stopTimerCounter() {
if (this._timerCounter) {
this._timerCounter.stopTimer();
}
}
_timerCounterUptate() {
this._recordPlaybackTimestamp = this._recordPlaybackTimestamp + 1;//计时
if (this._recordPlaybackTimestamp >= this._recordPlaybackMaxTime) {
this._stopTimerCounter();
loger.log("录制回放结束...当前时间->", this._recordPlaybackTimestamp, " 总时间->", this._recordPlaybackMaxTime);
this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": STOP});
return;
}
loger.log("录制回放中...", this._recordPlaybackTimestamp);
this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": this._recordPlaybackTimestamp});
//各个APE模块根据时间查找消息数据
this._searchMessageFromTime(this._recordPlaybackTimestamp, this._conferApeMssages);
this._searchMessageFromTime(this._recordPlaybackTimestamp, this._chatApeMssages);
this._searchMessageFromTime(this._recordPlaybackTimestamp, this._docApeMssages);
this._searchMessageFromTime(this._recordPlaybackTimestamp, this._whiteApeMssages);
this._searchMessageFromTime(this._recordPlaybackTimestamp, this._videoApeMssages);
this._searchMessageFromTime(this._recordPlaybackTimestamp, this._audioApeMssages);
}
//加载录制文件
readyRecordPlay() {
this.initReplay();
loger.log("读取回放数据");
//let url = `http://123.56.73.119:80/h5dev/20170306/1357644520_20170306.rec`;
let url = `http://${ GlobalConfig.RecordServerIP}:${ GlobalConfig.RecordServerPort}/${GlobalConfig.recordFileName}`;
loger.log(url);
fetch(url, {
timeout: 90000 //加载文件超时时间1分30秒
})
.then(ret => {
if (ret.ok) {
return ret.arrayBuffer();
} else {
loger.error(`读取回放数据-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
throw '';
}
})
.then(ret => {
if (ret) {
loger.log('读取回放数据-完成');
this._loadRecordDataSuccess(ret);
} else {
loger.warn('读取回放数据-失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
}
})
.catch(err => {
loger.error(`读取回放数据.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
});
}
_loadRecordDataSuccess(arrayBuffer) {
loger.log("获取录制回放数据的长度", arrayBuffer.byteLength);
if (parseBuffer) {
parseBuffer.clear();
parseBuffer.append(arrayBuffer);
//解析数据
this.parseArrayBuf();
}
}
//解析数据
parseArrayBuf() {
//this._messages = {};
let byteLength = parseBuffer.offset;
parseBuffer.byteOffset = 0;
var position = 0;
while (position < byteLength) {
let timestamp = parseBuffer.readUInt32(position);
position += 4;//4字节
let byteLen = parseBuffer.readUInt32(position);
position += 4;//4字节
let byteData = parseBuffer.buffer.slice(position, (position + byteLen));
position += byteLen;
this._parseSaveSocketMsgReceivedHandler(byteData, timestamp);
//记录最后一个数据的时间戳作为整个录制回放的总时间戳
this._recordPlaybackMaxTime = timestamp;
}
this._recordPlaybackTimestamp = 0;
this._isReady = true;
this._stopTimerCounter();
GlobalConfig.recordPlaybackMaxTime = this._recordPlaybackMaxTime;
loger.log("录制回放数据解析完成,录制回放的总时间长为->", this._recordPlaybackMaxTime);
//console.log("_messages", this._messages);
loger.log("_conferApeMssages", this._conferApeMssages);
loger.log("_chatApeMssages", this._chatApeMssages);
loger.log("_docApeMssages", this._docApeMssages);
loger.log("_whiteApeMssages", this._whiteApeMssages);
loger.log("_videoApeMssages", this._videoApeMssages);
loger.log("_audioApeMssages", this._audioApeMssages);
this._emit(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, {"recordPlaybackMaxTime": this._recordPlaybackMaxTime});
}
//根据时间查找数据
_searchMessageFromTime(_timestamp, _apeMessages) {
let msgDataArr = _apeMessages[_timestamp];
if (!msgDataArr) {
//没有数据,需要查找当前时间点属于哪一个时间戳关键帧
} else {
//把时间点对应的数据发送,同一秒内有存在多个数据的情况
for (let i = 0; i < msgDataArr.length; i++) {
this._everSocketMsgReceivedHandler(msgDataArr[i].byteData, 0);
}
}
}
/*_searchMessageFromTime(_timestamp,_apeMessages){
let msgDataArr=this._messages[_timestamp];
if(!msgDataArr){
//没有数据,需要查找当前时间点属于哪一个时间戳关键帧
}else {
//把时间点对应的数据发送,同一秒内有存在多个数据的情况
for(let i=0;i<msgDataArr.length;i++){
this._everSocketMsgReceivedHandler(msgDataArr[i].byteData);
}
}
}*/
//method------------外部接口-------------------------------------
//开始播放
startRecordPlayback(_param) {
if (!this._isReady) {
return {"code": ApeConsts.RETURN_FAILED, "data": "录制回放还未准备完成"};
}
this._startTimerCounter();
this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": PLAY});
}
//停止播放
stopRecordPlayback(_param) {
this._recordPlaybackTimestamp = 0;
this._stopTimerCounter();
this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": STOP});
}
//暂停播放
pauseRecordPlayback(_param) {
this._stopTimerCounter();
this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": PAUSE});
}
//跳转到指定时间点播放
seekRecordPlayback(_param) {
if (!this._isReady) {
return {"code": ApeConsts.RETURN_FAILED, "data": "录制回放还未准备完成"};
}
if (!_param || !_param.time) {
return {"code": ApeConsts.RETURN_FAILED, "data": "参数不正确"};
}
//先暂停,更改进行的时间
this._stopTimerCounter()
this._recordPlaybackTimestamp = _param.time || 0;
//各个ape模块查找关键帧数据
this._searchKeyfram();
}
_searchKeyfram() {
//查找关键帧,找到关键帧后再继续播放
this._searchApeMessageKeyfram(this._conferApeMssages, ApeConsts.CONFERENCE_SESSION_ID);
this._searchApeMessageKeyfram(this._docApeMssages, ApeConsts.DOCSHARING_SESSION_ID);
this._searchApeMessageKeyfram(this._whiteApeMssages, ApeConsts.WHITEBOARD_SESSION_ID);
this._searchApeMessageKeyfram(this._videoApeMssages, ApeConsts.VIDEO_SESSION_ID);
this._searchApeMessageKeyfram(this._audioApeMssages, ApeConsts.AUDIO_SESSION_ID);
//聊天模块的比较特殊,消息是累计的
this._searchChatApeMessageKeyfram(this._chatApeMssages, ApeConsts.CHAT_SESSION_ID);
//各个ape模块无论有没有找到关键帧数据,都继续播放
this._startTimerCounter();
}
//查找ape关键帧数据
_searchApeMessageKeyfram(_apeMessages, _apeId) {
let messageItem;
let keyFrameSeekTime = 0;
for (let i = this._recordPlaybackTimestamp; i > 0; i--) {
messageItem = _apeMessages[i];
if (messageItem) {
keyFrameSeekTime = (this._recordPlaybackTimestamp - i)
loger.log("SEEK->APE", ApeConsts(_apeId), this._recordPlaybackTimestamp, "查找到相连的timestamp->", i, '需要seek->', keyFrameSeekTime, "秒");
//把时间点对应的数据发送,同一秒内有存在多个数据的情况
for (let k = 0; k < messageItem.length; k++) {
this._everSocketMsgReceivedHandler(messageItem[k].byteData, keyFrameSeekTime);
}
if (_apeId == ApeConsts.AUDIO_SESSION_ID || _apeId == ApeConsts.VIDEO_SESSION_ID) {
this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {
"status": SEEK,
"keyFrameSeekTime": keyFrameSeekTime
});
}
return;
}
}
loger.log("SEEK->APE", ApeConsts(_apeId), this._recordPlaybackTimestamp, "没有查找到相连的数据");
}
//查找聊天模块ape关键帧数据,聊天模块比较特殊,消息是累积的,当前时间戳之前的都需要显示
_searchChatApeMessageKeyfram(_apeMessages) {
let messageItem;
let keyFrameSeek = 0;
for (let i = this._recordPlaybackTimestamp; i > 0; i--) {
messageItem = _apeMessages[i];
if (messageItem) {
//把时间点对应的数据发送,同一秒内有存在多个数据的情况
for (let i = 0; i < messageItem.length; i++) {
this._everSocketMsgReceivedHandler(messageItem[i].byteData, 0);
}
}
}
}
}
RecordPlayBackParse.prototype.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS = RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS = 'class_join_recordPlayback_success';//加入录制回放成功
export default new RecordPlayBackParse;
... ...
... ... @@ -4,6 +4,9 @@ import MessageTypes from 'MessageTypes';
import GlobalConfig from 'GlobalConfig';
import MD5 from "md5";
import ApeConsts from 'apes/ApeConsts';
import iphunter from 'iphunter';
import fetchJsonp from 'fetch-jsonp';
// 日志对象
const loger = Loger.getLoger('Sass');
... ... @@ -37,8 +40,8 @@ class Sass extends Emiter {
*/
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);
loger.log(url);
loger.log(_initInfo);
fetch(url, {
timeout: 5000
})
... ... @@ -85,7 +88,7 @@ class Sass extends Emiter {
// Sass校验开始-->密码校验(如果需要密码)--->MD5校验----------------------------------------------------
passwordAndMd5Checking(_param) {
loger.log('2.开始Sass校验');
console.log(_param);
loger.log(_param);
confInfo = _param;
// 密码校验
if (confInfo.passwordRequired === 'true' || confInfo.passwordRequired === true) {
... ... @@ -114,7 +117,7 @@ class Sass extends Emiter {
}
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);
loger.log('3.课堂密码校验', url);
fetch(url, {
timeout: 5000
})
... ... @@ -122,7 +125,7 @@ class Sass extends Emiter {
if (ret.status === 200) {
return ret.text();
} else {
loger.error(`会议密码校验-网络异常.状态码:${ret.status}`);
loger.error(`课堂密码校验-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_NETWORK);
throw '';
}
... ... @@ -130,20 +133,20 @@ class Sass extends Emiter {
.then(ret => {
let rectObj = JSON.parse(ret);
if (rectObj.flag === 'false' || rectObj.flag === false) {
loger.error(`会议密码校验-失败.`);
loger.error(`课堂密码校验-失败.`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_PASSWORD_WRONG);
return;
}
if (rectObj.flag === 'true' || rectObj.flag === true) {
loger.log(`会议密码校验-成功.`);
loger.log(`课堂密码校验-成功.`);
this.sendMD5Checking();
return;
}
loger.error(`会议密码校验-协议异常.`, rectObj);
loger.error(`课堂密码校验-协议异常.`, rectObj);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PROTOCOL);
})
.catch(err => {
loger.error(`会议密码校验-异常.状态码:${err}`);
loger.error(`课堂密码校验-异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FAILED);
});
}
... ... @@ -182,7 +185,7 @@ class Sass extends Emiter {
GlobalConfig.maxAudioChannels=confInfo.maxAudioChannels;
GlobalConfig.maxMediaChannels=confInfo.maxMediaChannels;*/
loger.log('MD5校验完成');
console.log(ret);
loger.log(ret);
this._emit(Sass.SUCCESS, ret);
} else {
loger.log('MD5校验-失败.');
... ... @@ -196,7 +199,7 @@ class Sass extends Emiter {
});
}
// 获取会议基本详情------------------------------------------------------------------------------------
// 获取课堂基本详情------------------------------------------------------------------------------------
getClassDetail() {
let url = `http://${confInfo.portal}/3m/meeting/getClassH5.do?classNumber=${confInfo.classId}`;
loger.log('获取Class详情.', url);
... ... @@ -227,7 +230,7 @@ class Sass extends Emiter {
});
}
//获取课堂会议的完整信息--------------------------------------------------------------------------------
//获取课堂课堂的完整信息--------------------------------------------------------------------------------
getClassParam() {
/*
参数 (application/x-www-form-urlencoded):
... ... @@ -246,10 +249,10 @@ class Sass extends Emiter {
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);
var authId = MD5(GlobalConfig.classId + "" + timestamp);//课堂号+时间戳 的字符串,转成MD5
let url = `http://${GlobalConfig.portal}/3m/api/meeting/detail.do?meetingNumber=${GlobalConfig.classId}&timestamp=${timestamp}&authId=${authId}`;
loger.log('5.获取课堂课堂的完整信息 ');
loger.log(url);
fetch(url, {
timeout: 5000
})
... ... @@ -257,7 +260,7 @@ class Sass extends Emiter {
if (ret.ok) {
return ret.json();
} else {
loger.error(`获取课堂会议的完整信息-网络异常.状态码:${ret.status}`);
loger.error(`获取课堂课堂的完整信息-网络异常.状态码:${ret.status}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
throw '';
... ... @@ -265,15 +268,15 @@ class Sass extends Emiter {
})
.then(ret => {
if (ret.code === 0) {
loger.log('获取课堂会议的完整信息完成');
loger.log('获取课堂课堂的完整信息完成');
this._emit(Sass.CLASS_GET_CLASS_PARAM, ret);
} else {
loger.warn('获取课堂会议的完整信息 失败.');
loger.warn('获取课堂课堂的完整信息 失败.');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
}
})
.catch(err => {
loger.error(`获取课堂会议的完整信息异常.状态码:${err}`);
loger.error(`获取课堂课堂的完整信息异常.状态码:${err}`);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
});
}
... ... @@ -291,6 +294,10 @@ class Sass extends Emiter {
0 成功, 1 验证信息错误
*/
sassDeleteDocument(_param) {
if(GlobalConfig.isRecordPlayBack){
loger.log('录制回放中,能删除文档');
return;
}
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}`;
... ... @@ -337,6 +344,10 @@ class Sass extends Emiter {
code 0 成功 1 课堂号为空 2 无效的课堂号 3 验证信息错误*/
saveClassStatusInfo(_param) {
if(GlobalConfig.isRecordPlayBack){
loger.log('录制回放中,不需要保存课堂信息');
return;
}
//{"classStatusInfo":classStatusInfo}
var timestamp = new Date().getTime();
var authId = MD5(confInfo.classId + "" + timestamp);// (classId+timestamp)的字符串,转成MD5
... ... @@ -383,24 +394,28 @@ class Sass extends Emiter {
//保存录制的信息,主要是录制文件的名称,必须和MCU录制的文件名相同
saveClassRecordContrlInfo(_param) {
if(GlobalConfig.isRecordPlayBack){
loger.log('录制回放中,不需要保存');
return;
}
loger.log('保存开始录制信息');
let key = "3mang123A";
let siteID = GlobalConfig.siteId;
let key = "3mang123A";
let siteID = GlobalConfig.siteId;
let meetingID = GlobalConfig.classId;
let userID = GlobalConfig.userId;
let userName = GlobalConfig.userName;
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 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 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);
... ... @@ -420,7 +435,7 @@ class Sass extends Emiter {
loger.log('保存开始录制信息 完成');
this._emit(Sass.CLASS_SAVE_RECORD_INFO_SUCCESS, _param);
} else {
loger.warn('保存开始录制信息 失败.',ret);
loger.warn('保存开始录制信息 失败.', ret);
}
})
.catch(err => {
... ... @@ -428,7 +443,6 @@ class Sass extends Emiter {
});
}
}
Sass.prototype.SUCCESS = Sass.SUCCESS = 'Sass_success';
... ... @@ -437,8 +451,8 @@ Sass.prototype.CLASS_GET_CLASS_PARAM = Sass.CLASS_GET_CLASS_PARAM = 'sass_class_
Sass.prototype.CLASS_GET_CLASS_DETAIL = Sass.CLASS_GET_CLASS_DETAIL = 'sass_class_getClassDetail_message';
Sass.prototype.DELETE_DOCUMENT_SUCCESS = Sass.DELETE_DOCUMENT_SUCCESS = 'sass_class_deleteDocumentSuccess_message';//删除文档成功
Sass.prototype.CLASS_SAVE_STATUS_INFO_SUCCESS = Sass.CLASS_SAVE_STATUS_INFO_SUCCESS = 'sass_class_saveClassStatusInfoSuccess_message';//保存会议状态信息
Sass.prototype.CLASS_SAVE_RECORD_INFO_SUCCESS = Sass.CLASS_SAVE_RECORD_INFO_SUCCESS = 'sass_class_saveClassRecordInfoSuccess_message';//保存录制会议信息
Sass.prototype.CLASS_SAVE_STATUS_INFO_SUCCESS = Sass.CLASS_SAVE_STATUS_INFO_SUCCESS = 'sass_class_saveClassStatusInfoSuccess_message';//保存课堂状态信息
Sass.prototype.CLASS_SAVE_RECORD_INFO_SUCCESS = Sass.CLASS_SAVE_RECORD_INFO_SUCCESS = 'sass_class_saveClassRecordInfoSuccess_message';//保存录制课堂信息
export default new Sass;
... ...
import Emiter from 'Emiter';
import Loger from 'Loger';
import MessageTypes from 'MessageTypes';
import GlobalConfig from 'GlobalConfig';
import MD5 from "md5";
import ApeConsts from 'apes/ApeConsts';
import iphunter from 'iphunter';
import Server from "config/Server";
import fetchJsonp from 'fetch-jsonp';
// 日志对象
const loger = Loger.getLoger('ServerCheck');
//ip选点流程的状态
let isRequestMcuCallback = false;//是否获取最佳mcu返回
let isRequestMsCallback = false;//是否获取ms最佳返回
let isTestFromSass=false;
let isTestFromServer=false;
let tempMcuIp="";
let tempMcuPort="";
let tempMsIp="";
let tempMsPort="";
let msDefaultPort=":1935";
let mcuDefaultPort="7777";
let speedTestPort = ':5555';//测速端口统一
let checkMcuIpGroup =[];//储存MCU需要查询的ip数组
let checkMsIpGroup =[];//储存MCU需要查询的ip数组
class ServerCheck extends Emiter {
constructor() {
super();
}
//根据userIp获取ip相关的信息,参数是userIp
getUserIpInfo(token, userIp) {
//重置ip选点流程状态
isRequestMcuCallback = false;
isRequestMsCallback = false;
isTestFromSass=false;
isTestFromServer=false;
checkMcuIpGroup =[];
checkMsIpGroup =[];
let userIpInfo = new Object;
userIpInfo.ret = -1;
let ip = userIp;
let md5Str = MD5("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3");//("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3"),转成MD5
let timestamp = new Date().getTime();
let location = `http://ipapi.ipip.net/find?addr=${ip}&sid=14&uid=5237&sig=${md5Str}&_=${timestamp}`;
loger.log('获取IP信息 ', userIp, location);
fetchJsonp(location, {
timeout: 3000,
}).then(function (response) {
return response.json()
}).then(function (json) {
loger.log('获取IP信息返回', json)
if (json) {
userIpInfo.ret = json.ret;
userIpInfo.country = json.data[0];//国家
userIpInfo.province = json.data[1];//省份
userIpInfo.city = json.data[2];//城市
userIpInfo.isp = json.data[4];//运营商
}
this.serverGetUserIpInfoCallback(userIpInfo);
}.bind(this)).catch(function (ex) {
loger.log('获取IP信息失败', ex.message)
this.serverGetUserIpInfoCallback(userIpInfo);
}.bind(this));
}
//获取ip信息返回
serverGetUserIpInfoCallback(userIpInfo) {
loger.log("获取IP详情,开始处理", userIpInfo);
if (userIpInfo.ret == "ok") {
GlobalConfig.country = userIpInfo.country;//国家
GlobalConfig.city = userIpInfo.city;//城市
GlobalConfig.province = userIpInfo.province;//服务商
GlobalConfig.isp = userIpInfo.isp;//服务商
loger.log("获取ip详情成功,country:" + GlobalConfig.country + ",city:" + GlobalConfig.city + ",isp:" + GlobalConfig.isp);
this._chooseBestIpFromServer();
}
else {
loger.log("获取ip详情失败");
this._chooseBestIpFromSassParam();
}
}
//从IPIP服务列表中选择最快的IP
_chooseBestIpFromServer() {
loger.log("从Server服务列表中选择最快的IP");
isRequestMcuCallback=false;
isRequestMsCallback=false;
isTestFromServer=true;
isTestFromSass=false;
//country, province, ctiy, isp, jsona
checkMcuIpGroup =this._returnServerMCU(
GlobalConfig.country,
GlobalConfig.province,
GlobalConfig.city,
GlobalConfig.isp,
Server.serverList);
checkMsIpGroup = this._returnServerMS(
GlobalConfig.country,
GlobalConfig.province,
GlobalConfig.city,
GlobalConfig.isp,
Server.serverList);
let mcuArr=[];
let msArr=[];
for(let i in checkMcuIpGroup){
if(checkMcuIpGroup[i]){
mcuArr.push(checkMcuIpGroup[i].ip+speedTestPort);
}
}
for(let k in checkMsIpGroup){
if(checkMsIpGroup[k]){
msArr.push(checkMsIpGroup[k].ip+speedTestPort);
}
}
this.getBestMcuServer(mcuArr);
this.getBestMsServer(msArr);
}
//从Sass返回的msList mcuList中选点
_chooseBestIpFromSassParam() {
loger.log("从Sass服务列表中选择最快的IP");
isRequestMcuCallback = false;
isRequestMsCallback = false;
isTestFromSass=false;
isTestFromServer=false;
checkMcuIpGroup =GlobalConfig.mcuList;
checkMsIpGroup =GlobalConfig.msList;
//MCU
let mcuIpGroup = [];
for (let i = 0; i < checkMcuIpGroup.length; i++) {
let ipPort = checkMcuIpGroup[i].ip+speedTestPort;
mcuIpGroup.push(ipPort)
}
this.getBestMcuServer(mcuIpGroup);
//MS
let msIpGroup = [];
for (let k = 0; k < checkMsIpGroup.length; k++) {
let ipPort = checkMsIpGroup[k].ip+speedTestPort;
msIpGroup.push(ipPort)
}
this.getBestMsServer(msIpGroup);
}
//获取最快的MCU服务器地址,参数是一个ip数组
getBestMcuServer(_param) {
loger.log('开始MCU选点 ', _param);
if(_param==null||_param.length<1){
this._getBestMcuServerCallbackHandler("")
return;
}
iphunter(_param, function (fatest_ip_response) {
if (!fatest_ip_response) {
loger.warn('getBestMcuServer -> nothing!');
this._getBestMcuServerCallbackHandler("")
} else {
//loger.log('getBestMcuServer done -> ', fatest_ip_response);
this._getBestMcuServerCallbackHandler(fatest_ip_response)
}
}.bind(this), 3000);
}
//获取最快的MS服务器地址,参数是一个ip数组
getBestMsServer(_param) {
loger.log('开始MS选点 ', _param);
if(_param==null||_param.length<1){
this._getBestMsServerCallbackHandler("")
return;
}
iphunter(_param, function (fatest_ip_response) {
if (!fatest_ip_response) {
loger.warn('getBestMsServer -> nothing!');
this._getBestMsServerCallbackHandler("");
} else {
//loger.log('getBestMsServer done -> ', fatest_ip_response);
this._getBestMsServerCallbackHandler(fatest_ip_response);
}
}.bind(this), 3000);
}
_getBestMcuServerCallbackHandler(_data) {
loger.log("MCU选点返回1", _data);
if (isRequestMcuCallback) {
loger.log("MCU选点,已经有返回");
return;
}
isRequestMcuCallback = true;
if (_data) {
let server = _data.split(":");
if (server[0]) {
tempMcuIp= server[0];
}
tempMcuPort=mcuDefaultPort;
for(let i=0;i<checkMcuIpGroup.length;i++){
if(tempMcuIp==checkMcuIpGroup[i].ip){
tempMcuPort=checkMcuIpGroup[i].port||mcuDefaultPort;
break;
}
}
}
loger.log("MCU选点返回2",tempMcuIp,tempMcuPort);
this._startConnectMcu();
}
_getBestMsServerCallbackHandler(_data) {
loger.log("MS选点返回1", _data);
if (isRequestMsCallback) {
loger.log("_getBestMsServerCallbackHandler,已经有返回");
return;
}
isRequestMsCallback = true;
if (_data) {
let server = _data.split(":");
if (server[0]) {
tempMsIp= server[0];
}
tempMsPort=msDefaultPort;
for(let i=0;i<checkMsIpGroup.length;i++){
if(tempMsPort==checkMsIpGroup[i].ip){
tempMsPort=checkMsIpGroup[i].port||msDefaultPort;
break;
}
}
}
loger.log("MS选点返回2", tempMsIp,tempMsPort);
this._startConnectMcu();
}
//ip选点结束,开始连接MCU
_startConnectMcu() {
if (isRequestMcuCallback && isRequestMsCallback) {
if (isTestFromServer && !isTestFromSass) {
//从Server服务列表中选点结束,如果没有选到合适的,从Sass的列表中获取
if(!tempMcuIp||!tempMsIp){
this._chooseBestIpFromSassParam();
}else {
GlobalConfig.MCUServerIP=tempMcuIp;
GlobalConfig.MCUServerPort=tempMcuPort;
GlobalConfig.MSServerIP=tempMsIp;
GlobalConfig.MSServerPort=tempMsPort;
loger.log("Server选点完成", "mcu-->",GlobalConfig.MCUServerIP,GlobalConfig.MCUServerPort,"ms---->",GlobalConfig.MSServerIP,GlobalConfig.MSServerPort);
this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
}
} else {
//从Sass返回的服务列表中选点结束
if(tempMcuIp){
GlobalConfig.MCUServerIP=tempMcuIp;
GlobalConfig.MCUServerPort=tempMcuPort;
}
if(tempMsIp){
GlobalConfig.MSServerIP=tempMsIp;
GlobalConfig.MSServerPort=tempMsPort;
}
loger.log("Sass选点完成", "mcu-->",GlobalConfig.MCUServerIP,GlobalConfig.MCUServerPort,"ms---->",GlobalConfig.MSServerIP,GlobalConfig.MSServerPort);
this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
}
} else {
loger.warn("_startConnectMcu->正在选点", isRequestMcuCallback, isRequestMsCallback);
}
}
//检测MCU连接地址
_returnServerMCU(country, province, ctiy, isp, jsona) {
let countryData=jsona.MCU[country];
//按country没有查找到就返回default
if(!countryData){
countryData=jsona.MCU.default;
loger.log("_returnServerMCU->countryData->default",countryData);
return countryData;
}
if(country!="中国"){
loger.log("_returnServerMCU->countryData",countryData);
return countryData;
}
//中国的需要细分
//按isp查找
let ispData=countryData.isp[isp];
//isp查找到就返回
if(ispData){
loger.log("_returnServerMCU->ispData",ispData);
return ispData;
}
//isp没查找到,用province
let provinceData=countryData.province[province];
//用province查找到就返回
if(provinceData){
loger.log("_returnServerMCU->provinceData",provinceData);
return provinceData;
}
//isp province都没有,使用default
let defaultData=countryData.default
if(defaultData){
loger.log("_returnServerMCU->defaultData",defaultData);
return defaultData;
}else {
loger.log("_returnServerMCU->defaultData","");
return [];
}
return [];
}
//检测MS连接地址
//Config.ipInfo
_returnServerMS(country, province, ctiy, isp, jsona) {
let countryData=jsona.MS[country];
//按country没有查找到就返回default
if(!countryData){
countryData=jsona.MS.default;
loger.log("_returnServerMS->countryData->default",countryData);
return countryData;
}
if(country!="中国"){
loger.log("_returnServerMS->countryData",countryData);
return countryData;
}
//中国的需要细分
//按isp查找
let ispData=countryData.isp[isp];
//isp查找到就返回
if(ispData){
loger.log("_returnServerMS->ispData",ispData);
return ispData;
}
//isp没查找到,用province
let provinceData=countryData.province[province];
//用province查找到就返回
if(provinceData){
loger.log("_returnServerMS->provinceData",provinceData);
return provinceData;
}
//isp province都没有,使用default
let defaultData=countryData.default
if(defaultData){
loger.log("_returnServerMS->defaultData",defaultData);
return defaultData;
}else {
loger.log("_returnServerMS->defaultData","");
return [];
}
return [];
}
}
ServerCheck.prototype.SEVER_CHECK_BEST_IP_SUCCESS = ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS = 'severCheck_checkBestIpSuccess_message';//获取最快的MS地址
export default new ServerCheck;
... ...
... ... @@ -32,6 +32,7 @@ class TimerCounter {
}
//停止
stopTimer(){
if(!this.isStart) return;
console.log("stopTimer",this.counter);
this.isStart=false;
this.timerClear();
... ...
... ... @@ -15,364 +15,373 @@
import pdu from 'pdus';
import Emiter from 'Emiter';
import mcu from 'mcu';
import McuObj from 'mcu';
import Loger from 'Loger';
import MessageTypes from 'MessageTypes';
import ApeConsts from './ApeConsts';
import ArrayBufferUtil from 'libs/ArrayBufferUtil';
import PduConsts from 'pdus/PduConsts';
import GlobalConfig from 'GlobalConfig';
import RecordPlayBackParse from 'RecordPlayBackParse';
// 日志对象
const loger = Loger.getLoger('Ape');
export default class Ape extends Emiter {
constructor(
session_id,
session_name,
session_tag
) {
super();
this._session_id = session_id;
this._channel_id = session_id; // session_id === channel_id
this._session_name = session_name;
this._session_tag = session_tag;
this._session_channels = {};
this._adapter_pdu = new pdu['RCAdapterPdu'];
this._classInfo = null;
this._rCArrayBufferUtil = ArrayBufferUtil;
this._apeDelayed = false;
this._apeDelayedMsgs = [];
this._apeDelayedTimer = 0;
//Ape 通用消息处理
this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
this.on(pdu.RCPDU_CHANNEL_JOIN_RESPONSE, this._joinChannelHandler.bind(this));
this.on(pdu.RCPDU_REG_ADAPTER, this._pduMessageHandler.bind(this));
//先收到onJoinSessionHandlerSuccess 后收到 onJoinChannelHandlerSuccess
// 监听底层MCU会议
this.mcu = mcu;
this.mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuConferenceJoinSuccessHandler.bind(this));
this.mcu.registerApe(this);
}
regResponsePduHandler() {
}
// 消息处理
_pduMessageHandler(regBuffer) {
//loger.log("RCPDU_REG_ADAPTER==============================");
if (this._apeDelayed) {
// this._apeDelayedMsgs.push(regBuffer);
// this._apeDelayedStart();
setTimeout(() => {
this._pduRegAdapterHandler(regBuffer);
},GlobalConfig.mcuDelay|| 12000);
return;
constructor(session_id,
session_name,
session_tag) {
super();
this._session_id = session_id;
this._channel_id = session_id; // session_id === channel_id
this._session_name = session_name;
this._session_tag = session_tag;
this._session_channels = {};
this._adapter_pdu = new pdu['RCAdapterPdu'];
this._classInfo = null;
this._rCArrayBufferUtil = ArrayBufferUtil;
this._apeDelayed = false;
this._apeDelayedMsgs = [];
this._apeDelayedTimer = 0;
//Ape 通用消息处理
this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
this.on(pdu.RCPDU_CHANNEL_JOIN_RESPONSE, this._joinChannelHandler.bind(this));
this.on(pdu.RCPDU_REG_ADAPTER, this._pduMessageHandler.bind(this));
//先收到onJoinSessionHandlerSuccess 后收到 onJoinChannelHandlerSuccess
// 监听底层MCU课堂
this.mcu = McuObj;
this.mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuConferenceJoinSuccessHandler.bind(this));
this.mcu.registerApe(this);
//录制回放
this.recordPlayBackParse = RecordPlayBackParse;
this.recordPlayBackParse.on(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, this._joinRecordPlaybackSuccessHandler.bind(this));
this.recordPlayBackParse.registerApe(this);
}
this._pduRegAdapterHandler(regBuffer);
}
// _apeDelayedStart() {
// if (this._apeDelayed && !this._apeDelayedTimer) {
// this._apeDelayedTimer = setInterval(this._delayedMsgHandler.bind(this), this._classInfo['mcuDelay'] || 10000);
// }
// }
// _apeDelayedStop() {
// clearInterval(this._apeDelayedTimer);
// this._apeDelayedTimer = 0;
// }
// // 延迟消息处理
// _delayedMsgHandler() {
// if (this._apeDelayedMsgs.length) {
// this._pduRegAdapterHandler(this._apeDelayedMsgs.pop());
// if (!this._apeDelayedMsgs.length) this._apeDelayedStop();
// }
// }
// 数据同步处理
_pduRegAdapterHandler(regBuffer) {
let regPdu = pdu['RCAdapterPdu'].decode(regBuffer);
let regItems = regPdu.item;
let regItemSize = regItems.length;
//loger.log(this._session_name + '数据同步消息');
loger.log(this._session_name + '数据同步消息.同步条数', regItemSize);
//console.log(regPdu);
for (var i = 0; i < regItemSize; ++i) {
let regItem = regItems[i];
let regItemType = regItem.type;
let regItemData = regItem.itemData;
//根据数据包中的type处理数据是否同步
if (pdu.RCPDU_REG_UPDATE_OBJ !== regItemType) {
if (pdu.RCPDU_REG_RESPONSE_OBJ == regItemType) {
let regResponsePdu = pdu['RCRegistryResponseObjPdu'].decode(regItemData);
this.regResponsePduHandler(regResponsePdu);
}
// 只处理两种类型
continue;
}
//具体的数据包
let regUpdatedItem = pdu['RCRegistryUpdateObjPdu'].decode(regItemData);
let sub_type = regUpdatedItem.subType;
let object_id = regUpdatedItem.objId;
let user_data = regUpdatedItem.userData;
loger.log('REG OBJECT EVENT ->', pdu.id2type(sub_type));
switch (sub_type) {
case pdu.RCPDU_REG_ROSTER_INSERT_PDU:
let rosterInsertData = pdu['RCRegstryRosterInsertItemPdu'].decode(user_data);
let rosterInsertItems = rosterInsertData.items;
let rosterInsertItemsLen = rosterInsertItems.length;
for (let i = 0; i < rosterInsertItemsLen; ++i) {
let record = rosterInsertItems[i];
let recordId = record.item_id;
let recordData = pdu['RCNodeInfoRecordPdu'].decode(record.item_data);
this.rosterInsertHandler(recordId, recordData);
}
break;
case pdu.RCPDU_REG_ROSTER_DELETE_PDU:
let rosterDelData = pdu['RCRegistryRosterDeleteItemPdu'].decode(user_data);
this.rosterDelHandler(rosterDelData.nodeId);
break;
case pdu.RCPDU_REG_ROSTER_UPDATE_PDU:
let rosterUpdateData = pdu['RCRegistryRosterUpdateItemPdu'].decode(user_data);
let rosterUpdateItems = rosterUpdateData.items;
let rosterUpdateItemsLen = rosterUpdateItems.length;
for (let i = 0; i < rosterUpdateItemsLen; ++i) {
let node = rosterUpdateItems[i];
let nodeId = node.nodeId;
let nodeData = pdu['RCNodeInfoRecordPdu'].decode(node.nodeData);
this.rosterUpdateHandler(nodeId, nodeData);
}
break;
case pdu.RCPDU_REG_TABLE_INSERT_PDU:
let tableInsertData = pdu['RCRegistryTableInsertItemPdu'].decode(user_data);
let tableInsertItems = tableInsertData.items;
let tableInsertItemsLen = tableInsertItems.length;
for (let i = 0; i < tableInsertItemsLen; ++i) {
let insertItem = tableInsertItems[i];
//loger.log("insertItem",insertItem);
this.tableInsertHandler(insertItem.owner, insertItem.itemIdx, insertItem.itemData);
regResponsePduHandler() {
}
//停止APE一切操作
stopApe() {
loger.log("stopApe==============================");
}
// 消息处理
_pduMessageHandler(regBuffer,_seekTime) {
let seekTime=_seekTime||0;//这个只有在录制回放的时候才有
//loger.log("RCPDU_REG_ADAPTER============seekTime",seekTime);
if (this._apeDelayed) {
// this._apeDelayedMsgs.push(regBuffer);
// this._apeDelayedStart();
setTimeout(() => {
this._pduRegAdapterHandler(regBuffer,seekTime);
}, GlobalConfig.mcuDelay || 2000);
return;
}
break;
case pdu.RCPDU_REG_TABLE_DELETE_PDU:
let tableDeleteData = pdu['RCRegistryTableDeleteItemPdu'].decode(user_data);
//console.log("tableDeleteData",object_id,tableDeleteData);
this.tableDeleteHandler(object_id, tableDeleteData);
break;
case pdu.RCPDU_REG_TABLE_UPDATE_PDU:
let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data);
let tableUpdateItems = tableUpdateData.items;
let tableUpdateItemsLen= tableUpdateItems.length;
loger.log("RCRegistryTableUpdateItemPdu "+tableUpdateItemsLen);
console.log(tableUpdateData);
for (let i = 0; i < tableUpdateItemsLen; ++i) {
let tableItem = tableUpdateItems[i];
this.tableUpdateHandler(tableItem.owner, tableItem.itemIdx, tableItem.itemData);
this._pduRegAdapterHandler(regBuffer,seekTime);
}
// 数据同步处理
_pduRegAdapterHandler(regBuffer,seekTime) {
let regPdu = pdu['RCAdapterPdu'].decode(regBuffer);
let regItems = regPdu.item;
let regItemSize = regItems.length;
//loger.log(this._session_name + '数据同步消息');
//loger.log(this._session_name + '数据同步消息.同步条数', regItemSize,"seekTime->",seekTime);
for (var i = 0; i < regItemSize; ++i) {
let regItem = regItems[i];
let regItemType = regItem.type;
let regItemData = regItem.itemData;
//根据数据包中的type处理数据是否同步
if (pdu.RCPDU_REG_UPDATE_OBJ !== regItemType) {
if (pdu.RCPDU_REG_RESPONSE_OBJ == regItemType) {
let regResponsePdu = pdu['RCRegistryResponseObjPdu'].decode(regItemData);
this.regResponsePduHandler(regResponsePdu);
}
// 只处理两种类型
continue;
}
//具体的数据包
let regUpdatedItem = pdu['RCRegistryUpdateObjPdu'].decode(regItemData);
let sub_type = regUpdatedItem.subType;
let object_id = regUpdatedItem.objId;
let user_data = regUpdatedItem.userData;
loger.log('REG OBJECT EVENT ->', pdu.id2type(sub_type));
switch (sub_type) {
case pdu.RCPDU_REG_ROSTER_INSERT_PDU:
let rosterInsertData = pdu['RCRegstryRosterInsertItemPdu'].decode(user_data);
let rosterInsertItems = rosterInsertData.items;
let rosterInsertItemsLen = rosterInsertItems.length;
for (let i = 0; i < rosterInsertItemsLen; ++i) {
let record = rosterInsertItems[i];
let recordId = record.item_id;
let recordData = pdu['RCNodeInfoRecordPdu'].decode(record.item_data);
this.rosterInsertHandler(recordId, recordData);
}
break;
case pdu.RCPDU_REG_ROSTER_DELETE_PDU:
let rosterDelData = pdu['RCRegistryRosterDeleteItemPdu'].decode(user_data);
this.rosterDelHandler(rosterDelData.nodeId);
break;
case pdu.RCPDU_REG_ROSTER_UPDATE_PDU:
let rosterUpdateData = pdu['RCRegistryRosterUpdateItemPdu'].decode(user_data);
let rosterUpdateItems = rosterUpdateData.items;
let rosterUpdateItemsLen = rosterUpdateItems.length;
for (let i = 0; i < rosterUpdateItemsLen; ++i) {
let node = rosterUpdateItems[i];
let nodeId = node.nodeId;
let nodeData = pdu['RCNodeInfoRecordPdu'].decode(node.nodeData);
this.rosterUpdateHandler(nodeId, nodeData);
}
break;
case pdu.RCPDU_REG_TABLE_INSERT_PDU:
let tableInsertData = pdu['RCRegistryTableInsertItemPdu'].decode(user_data);
let tableInsertItems = tableInsertData.items;
let tableInsertItemsLen = tableInsertItems.length;
for (let i = 0; i < tableInsertItemsLen; ++i) {
let insertItem = tableInsertItems[i];
//loger.log("insertItem",insertItem);
this.tableInsertHandler(insertItem.owner, insertItem.itemIdx, insertItem.itemData);
}
break;
case pdu.RCPDU_REG_TABLE_DELETE_PDU:
let tableDeleteData = pdu['RCRegistryTableDeleteItemPdu'].decode(user_data);
//console.log("tableDeleteData",object_id,tableDeleteData);
this.tableDeleteHandler(object_id, tableDeleteData);
break;
case pdu.RCPDU_REG_TABLE_UPDATE_PDU:
let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data);
let tableUpdateItems = tableUpdateData.items;
let tableUpdateItemsLen = tableUpdateItems.length;
//loger.log("RCRegistryTableUpdateItemPdu " + tableUpdateItemsLen);
loger.log(tableUpdateData);
for (let i = 0; i < tableUpdateItemsLen; ++i) {
let tableItem = tableUpdateItems[i];
this.tableUpdateHandler(tableItem.owner, tableItem.itemIdx, tableItem.itemData,seekTime);
}
break;
case pdu.RCPDU_REG_QUEUE_UPDATE_PDU:
case pdu.RCPDU_REG_QUEUE_DELETE_PDU:
case pdu.RCPDU_REG_QUEUE_INSERT_PDU:
loger.warn('REG QUEUE ARE IGNORED');
break;
}
}
break;
case pdu.RCPDU_REG_QUEUE_UPDATE_PDU:
case pdu.RCPDU_REG_QUEUE_DELETE_PDU:
case pdu.RCPDU_REG_QUEUE_INSERT_PDU:
loger.warn('REG QUEUE ARE IGNORED');
break;
}
}
}
rosterInsertHandler(recordId, recordData) {
loger.warn(this._session_name + ' rosterInsertHandler 应有子类具体覆盖处理.');
}
rosterUpdateHandler(nodeId, nodeData) {
loger.warn(this._session_name + ' rosterUpdateHandler 应有子类具体覆盖处理.');
}
rosterDelHandler(recordData) {
loger.warn(this._session_name + ' rosterDelHandler 应有子类具体覆盖处理.');
}
tableInsertHandler(tableId, record) {
loger.warn(this._session_name + ' tableInsertHandler 应有子类具体覆盖处理.');
}
tableUpdateHandler(ownerId, recordId, recordData) {
loger.warn(this._session_name + ' tableUpdateHandler 应有子类具体覆盖处理.');
}
tableDeleteHandler(tableId, record) {
loger.warn(this._session_name + ' tableDelHandler 应有子类具体覆盖处理.');
}
onJoinChannelHandlerSuccess(){
loger.warn(this._session_name + ' onJoinChannelHandlerSuccess 应有子类具体覆盖处理.');
}
onJoinSessionHandlerSuccess(){
loger.warn(this._session_name + ' onJoinSessionHandlerSuccess 应有子类具体覆盖处理.');
}
// 加入Session处理
_joinSessionHandler(data) {
loger.log(this._session_name, ' -> 加入Session');
this.onJoinSessionHandlerSuccess();
}
// 加入Channel处理
_joinChannelHandler(data) {
let joinedChannel = pdu['RCChannelJoinResponsePdu'].decode(data);
if (joinedChannel.result === pdu.RET_SUCCESS) {
loger.log(this._session_name, ' -> 加入Channel成功. ChannelId', joinedChannel.requestedChannelId);
this._session_channels[joinedChannel.requestedChannelId] = ApeConsts.CJS_JOINNED;
this.onJoinChannelHandlerSuccess();
} else {
loger.log(this._session_name, ' -> 加入Channel失败.', joinedChannel);
rosterInsertHandler(recordId, recordData) {
loger.warn(this._session_name + ' rosterInsertHandler 应有子类具体覆盖处理.');
}
rosterUpdateHandler(nodeId, nodeData) {
loger.warn(this._session_name + ' rosterUpdateHandler 应有子类具体覆盖处理.');
}
rosterDelHandler(recordData) {
loger.warn(this._session_name + ' rosterDelHandler 应有子类具体覆盖处理.');
}
tableInsertHandler(tableId, record) {
loger.warn(this._session_name + ' tableInsertHandler 应有子类具体覆盖处理.');
}
tableUpdateHandler(ownerId, recordId, recordData,seekTime) {
loger.warn(this._session_name + ' tableUpdateHandler 应有子类具体覆盖处理.');
}
tableDeleteHandler(tableId, record) {
loger.warn(this._session_name + ' tableDelHandler 应有子类具体覆盖处理.');
}
onJoinChannelHandlerSuccess() {
loger.warn(this._session_name + ' onJoinChannelHandlerSuccess 应有子类具体覆盖处理.');
}
}
// 依赖的会议创建完毕 - 发起Ape加入
_mcuConferenceJoinSuccessHandler(_data) {
loger.log('创建Ape->',
'SessionId',
this._session_id,
'SessionName',
this._session_name,
'SessionTag',
this._session_tag);
// 会议依赖底层会议信息
//this._classInfo = classInfo;
this._classInfo = GlobalConfig.getClassInfo();
var joinSessionPdu = new pdu['RCSessionJoinRequestPdu'];
joinSessionPdu.id = this._session_id;
joinSessionPdu.name = this._session_name;
joinSessionPdu.tag = this._session_tag;
joinSessionPdu.sessionData = this._adapter_pdu.toArrayBuffer();
this.sendUniform(joinSessionPdu, true);
var joinChannelPdu = new pdu['RCChannelJoinRequestPdu'];
joinChannelPdu.initiator = this.mcu.classInfo.nodeId;
joinChannelPdu.channelId = this._session_id;
this.send(joinChannelPdu);
}
// 注册Key对象
registerKey(id, name, tag, user_data) {
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_KEY;
// pack register key pdus
let registerKeyPdu = new pdu['RCRegistryRegisterKeyPdu'];
registerKeyPdu.id = id;
registerKeyPdu.name = name;
registerKeyPdu.tag = tag;
if (user_data.length) {
registerKeyPdu.userData = user_data;
onJoinSessionHandlerSuccess() {
loger.warn(this._session_name + ' onJoinSessionHandlerSuccess 应有子类具体覆盖处理.');
}
adapterItemPdu.itemData = registerKeyPdu.toArrayBuffer();
this._adapter_pdu.item.push(adapterItemPdu);
}
// 注册Object对象 等同于flash中的 RCRegistryOperator
registerObj(type, id, name, tag, owner, user_data) {
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_OBJ;
let registerObjPdu = new pdu['RCRegistryRegisterObjPdu'];
registerObjPdu.type = type;
registerObjPdu.objId = id;
registerObjPdu.name = name;
registerObjPdu.tag = tag;
if (owner) {
registerObjPdu.owner = owner;
// 加入Session处理
_joinSessionHandler(data) {
loger.log(this._session_name, ' -> 加入Session');
this.onJoinSessionHandlerSuccess();
}
if (user_data.length) {
registerObjPdu.userData = user_data;
// 加入Channel处理
_joinChannelHandler(data) {
let joinedChannel = pdu['RCChannelJoinResponsePdu'].decode(data);
if (joinedChannel.result === pdu.RET_SUCCESS) {
loger.log(this._session_name, ' -> 加入Channel成功. ChannelId', joinedChannel.requestedChannelId);
this._session_channels[joinedChannel.requestedChannelId] = ApeConsts.CJS_JOINNED;
this.onJoinChannelHandlerSuccess();
} else {
loger.log(this._session_name, ' -> 加入Channel失败.', joinedChannel);
}
}
adapterItemPdu.itemData = registerObjPdu.toArrayBuffer();
this._adapter_pdu.item.push(adapterItemPdu);
}
send(appPdu) {
loger.log('Ape发送数据NORMAL PDU');
console.log(appPdu);
//loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
// 依赖的课堂创建完毕 - 发起Ape加入
_mcuConferenceJoinSuccessHandler(_data) {
loger.log('创建Ape->',
'SessionId',
this._session_id,
'SessionName',
this._session_name,
'SessionTag',
this._session_tag);
// 课堂依赖底层课堂信息
//this._classInfo = classInfo;
this._classInfo = GlobalConfig.getClassInfo();
var joinSessionPdu = new pdu['RCSessionJoinRequestPdu'];
joinSessionPdu.id = this._session_id;
joinSessionPdu.name = this._session_name;
joinSessionPdu.tag = this._session_tag;
joinSessionPdu.sessionData = this._adapter_pdu.toArrayBuffer();
this.sendUniform(joinSessionPdu, true);
var joinChannelPdu = new pdu['RCChannelJoinRequestPdu'];
joinChannelPdu.initiator = this.mcu.classInfo.nodeId;
joinChannelPdu.channelId = this._session_id;
this.send(joinChannelPdu);
}
let normalPdu = pdu.create_normal_pdu(
appPdu.type,
this._classInfo.nodeId,
this._classInfo.classId,
this._session_id,
this._channel_id,
true,
true,
PduConsts.DP_TOP,
this._classInfo.topNodeID,
PduConsts.SEG_ONCE
);
normalPdu.data = appPdu.toArrayBuffer();
// Mcu发送
this.mcu.send(normalPdu);
}
// 发送当前APE(session uniform包)
sendUniform(appPdu, top) {
loger.log('Ape发送数据UNIFORM PDU');
console.log(appPdu);
//loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
// 依赖的录制回放创建完毕 - 发起Ape加入
_joinRecordPlaybackSuccessHandler(_data) {
loger.log('录制回放->Ape已经创建完毕->',
'SessionId',
this._session_id,
'SessionName',
this._session_name,
'SessionTag',
this._session_tag);
}
let uniformPdu = pdu.create_uniform_pdu(
appPdu.type,
this._classInfo.nodeId,
this._classInfo.classId,
this._session_id,
top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,
true,
PduConsts.DP_TOP,
top ? this._classInfo.topNodeID : (appPdu.peer || 0),
PduConsts.SEG_ONCE
);
uniformPdu.data = appPdu.toArrayBuffer();
// Mcu发送
this.mcu.send(uniformPdu);
}
sendChatUniform(appPdu, top) {
loger.log('Ape发送数据UNIFORM PDU');
console.log(appPdu);
//loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){
this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
// 注册Key对象
registerKey(id, name, tag, user_data) {
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_KEY;
// pack register key pdus
let registerKeyPdu = new pdu['RCRegistryRegisterKeyPdu'];
registerKeyPdu.id = id;
registerKeyPdu.name = name;
registerKeyPdu.tag = tag;
if (user_data.length) {
registerKeyPdu.userData = user_data;
}
adapterItemPdu.itemData = registerKeyPdu.toArrayBuffer();
this._adapter_pdu.item.push(adapterItemPdu);
}
let uniformPdu = pdu.create_uniform_pdu(
appPdu.type,
this._classInfo.nodeId,
this._classInfo.classId,
this._session_id,
top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,
true,
PduConsts.DP_TOP,
0,//flash中这个值设置为0
PduConsts.SEG_ONCE
);
uniformPdu.data = appPdu.toArrayBuffer();
// Mcu发送
this.mcu.send(uniformPdu);
}
// 注册Object对象 等同于flash中的 RCRegistryOperator
registerObj(type, id, name, tag, owner, user_data) {
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_OBJ;
let registerObjPdu = new pdu['RCRegistryRegisterObjPdu'];
registerObjPdu.type = type;
registerObjPdu.objId = id;
registerObjPdu.name = name;
registerObjPdu.tag = tag;
if (owner) {
registerObjPdu.owner = owner;
}
if (user_data.length) {
registerObjPdu.userData = user_data;
}
adapterItemPdu.itemData = registerObjPdu.toArrayBuffer();
this._adapter_pdu.item.push(adapterItemPdu);
}
send(appPdu) {
loger.log('Ape发送数据NORMAL PDU');
//console.log(appPdu);
//loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
let normalPdu = pdu.create_normal_pdu(
appPdu.type,
this._classInfo.nodeId,
this._classInfo.classId,
this._session_id,
this._channel_id,
true,
true,
PduConsts.DP_TOP,
this._classInfo.topNodeID,
PduConsts.SEG_ONCE
);
normalPdu.data = appPdu.toArrayBuffer();
// Mcu发送
this.mcu.send(normalPdu);
}
// 发送当前APE(session uniform包)
sendUniform(appPdu, top) {
loger.log('Ape发送数据UNIFORM PDU');
//console.log(appPdu);
//loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
let uniformPdu = pdu.create_uniform_pdu(
appPdu.type,
this._classInfo.nodeId,
this._classInfo.classId,
this._session_id,
top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,
true,
PduConsts.DP_TOP,
top ? this._classInfo.topNodeID : (appPdu.peer || 0),
PduConsts.SEG_ONCE
);
uniformPdu.data = appPdu.toArrayBuffer();
// Mcu发送
this.mcu.send(uniformPdu);
}
sendChatUniform(appPdu, top) {
loger.log('Ape发送数据UNIFORM PDU');
//console.log(appPdu);
//loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
let uniformPdu = pdu.create_uniform_pdu(
appPdu.type,
this._classInfo.nodeId,
this._classInfo.classId,
this._session_id,
top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,
true,
PduConsts.DP_TOP,
0,//flash中这个值设置为0
PduConsts.SEG_ONCE
);
uniformPdu.data = appPdu.toArrayBuffer();
// Mcu发送
this.mcu.send(uniformPdu);
}
}
... ...
... ... @@ -11,7 +11,7 @@ export default function ApeConsts(id) {
ApeConsts.CLASS_STATUS_WAIT= 0;//课堂还未开始
ApeConsts.CLASS_STATUS_STARTED= 1;//直播中
ApeConsts.CLASS_STATUS_PAUSE= 2;//暂停
ApeConsts.CLASS_STATUS_CLOSE= 3;//结束//这个是点击结束会议,把所有人踢出课堂,然后把状态值还原为0*************
ApeConsts.CLASS_STATUS_CLOSE= 3;//结束//这个是点击结束课堂,把所有人踢出课堂,然后把状态值还原为0*************
ApeConsts.CLASS_STATUS_UPTATE= 4;//更新课堂状态信息
ApeConsts.CLASS_WAIT_START = "class.wait.start";//课堂还未开始
... ... @@ -22,7 +22,7 @@ ApeConsts.CLASS_PAUSING = "class.update";//更新当前的状态信息
//课堂控制
ApeConsts.CLASS_ACTION_CLOSE_ALL=1;//所有人关闭会议
ApeConsts.CLASS_ACTION_CLOSE_ALL=1;//所有人关闭课堂
//课堂类型
ApeConsts.CLASS_TYPE_INTERACT= 1; // 互动课堂,通过MS转发音视频,不能进行H5观看
... ... @@ -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;//(助教)
... ...