李勇

Merge branch 'mcuClientBranch'

要显示太多修改。

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

此 diff 太大无法显示。
  1 +root: true
  2 +
  3 +env:
  4 + es6: true
  5 + node: true
  6 + browser: true
  7 + mocha: true
  8 +
  9 +ecmaFeatures:
  10 + modules: true
  11 +
  12 +extends:
  13 + "airbnb"
  14 +
  15 +rules:
  16 + quotes: 0
  17 + func-names: 0
  18 + comma-dangle: 0
  19 + no-new-func: 0
  20 + no-eq-null: 0
  21 + no-param-reassign: 0
  1 +.DS_Store
  2 +*.log
  3 +node_modules
  4 +src
  5 +test
  6 +examples
  7 +coverage
  1 +language: node_js
  2 +node_js:
  3 + - "iojs"
  1 +1.0.6 / 2017-2-3
  2 +==================
  3 +* update typescript config
  4 +
  5 +1.0.5 / 2016-12-29
  6 +==================
  7 +* update typescript support
  8 +
  9 +1.0.4 / 2016-12-23
  10 +==================
  11 +* add typescript support
  12 +
  13 +1.0.3 / 2016-12-04
  14 +==================
  15 +* add examples index-ie8.html
  16 +* remove `es6-promise` dependent
  17 +
  18 +1.0.2 / 2016-09-26
  19 +==================
  20 +* Use original url when Request error
  21 +
  22 +1.0.1 / 2016-08-14
  23 +==================
  24 +* Format code
  25 +* Update Readme
  26 +
  27 +1.0.0 / 2015-11-19
  28 +==================
  29 +* Remove Bower support
  30 +* Add jsonpCallback and jsonpCallbackFunction as options
  31 +
  32 +0.9.2 / 2015-08-11
  33 +==================
  34 +* Remove global export of fetchJsonp
  35 +
  36 +0.9.1 / 2015-08-11
  37 +==================
  38 +* Update removeScript fix legacy IE
  1 +# Maintaining
  2 +
  3 +## Releasing a new version
  4 +
  5 +This project follows [semver](http://semver.org/). So if you are making a bug
  6 +fix, only increment the patch level "1.0.x". If any new files are added, a
  7 +minor version "1.x.x" bump is in order.
  8 +
  9 +### Make a release commit
  10 +
  11 +To prepare the release commit:
  12 +
  13 +1. Change the npm [package.json](https://github.com/camsong/fetch-jsonp/blob/master/package.json)
  14 +`version` value to match.
  15 +2. Make a single commit with the description as "Fetch JSONP 1.x.x".
  16 +3. Finally, tag the commit with `v1.x.x`.
  17 +
  18 +```
  19 +$ git pull
  20 +$ vim package.json
  21 +$ git add package.json
  22 +$ git commit -m "Fetch JSONP 1.x.x"
  23 +$ git tag v1.x.x
  24 +$ git push
  25 +$ git push --tags
  26 +```
  1 +# 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)
  2 +
  3 +JSONP is NOT supported in standard Fetch API, https://fetch.spec.whatwg.org.
  4 +fetch-jsonp provides you same API to fetch JSONP like naive Fetch, also comes
  5 +with global `fetchJsonp` function.
  6 +
  7 +If you need a `fetch` polyfill for old browsers, try [github/fetch](http://github.com/github/fetch).
  8 +
  9 +## Installation
  10 +
  11 +You can install with `npm`.
  12 +
  13 +```
  14 +npm install fetch-jsonp
  15 +```
  16 +
  17 +## Promise Polyfill for IE
  18 +
  19 +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.
  20 +
  21 +```js
  22 +require('es6-promise').polyfill();
  23 +```
  24 +
  25 +## Usage
  26 +
  27 +The `fetch-jsonp` function supports any HTTP method. We'll focus on GET and POST
  28 +example requests.
  29 +
  30 +### Fetch JSONP in simple way
  31 +
  32 +```javascript
  33 +fetchJsonp('/users.jsonp')
  34 + .then(function(response) {
  35 + return response.json()
  36 + }).then(function(json) {
  37 + console.log('parsed json', json)
  38 + }).catch(function(ex) {
  39 + console.log('parsing failed', ex)
  40 + })
  41 +```
  42 +
  43 +### Set JSONP callback name, default is 'callback'
  44 +
  45 +```javascript
  46 +fetchJsonp('/users.jsonp', {
  47 + jsonpCallback: 'custom_callback'
  48 + })
  49 + .then(function(response) {
  50 + return response.json()
  51 + }).then(function(json) {
  52 + console.log('parsed json', json)
  53 + }).catch(function(ex) {
  54 + console.log('parsing failed', ex)
  55 + })
  56 +```
  57 +
  58 +### Set JSONP request timeout, default is 5000ms
  59 +
  60 +```javascript
  61 +fetchJsonp('/users.jsonp', {
  62 + timeout: 3000,
  63 + jsonpCallback: 'custom_callback'
  64 + })
  65 + .then(function(response) {
  66 + return response.json()
  67 + }).then(function(json) {
  68 + console.log('parsed json', json)
  69 + }).catch(function(ex) {
  70 + console.log('parsing failed', ex)
  71 + })
  72 +```
  73 +
  74 +### Caveats
  75 +
  76 +You need to call `.then(function(response) { return response.json(); })` in order
  77 +to keep consistent with Fetch API.
  78 +
  79 +## Browser Support
  80 +
  81 +![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)
  82 +--- | --- | --- | --- | --- |
  83 +Latest ✔ | Latest ✔ | 8+ ✔ | Latest ✔ | 6.1+ ✔ |
  84 +
  85 +# License
  86 +
  87 +MIT
  88 +
  89 +# Acknowledgement
  90 +
  91 +Thanks to [github/fetch](https://github.com/github/fetch) for bring Fetch to old browsers.
  1 +(function (global, factory) {
  2 + if (typeof define === 'function' && define.amd) {
  3 + define(['exports', 'module'], factory);
  4 + } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
  5 + factory(exports, module);
  6 + } else {
  7 + var mod = {
  8 + exports: {}
  9 + };
  10 + factory(mod.exports, mod);
  11 + global.fetchJsonp = mod.exports;
  12 + }
  13 +})(this, function (exports, module) {
  14 + 'use strict';
  15 +
  16 + var defaultOptions = {
  17 + timeout: 5000,
  18 + jsonpCallback: 'callback',
  19 + jsonpCallbackFunction: null
  20 + };
  21 +
  22 + function generateCallbackFunction() {
  23 + return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
  24 + }
  25 +
  26 + // Known issue: Will throw 'Uncaught ReferenceError: callback_*** is not defined'
  27 + // error if request timeout
  28 + function clearFunction(functionName) {
  29 + // IE8 throws an exception when you try to delete a property on window
  30 + // http://stackoverflow.com/a/1824228/751089
  31 + try {
  32 + delete window[functionName];
  33 + } catch (e) {
  34 + window[functionName] = undefined;
  35 + }
  36 + }
  37 +
  38 + function removeScript(scriptId) {
  39 + var script = document.getElementById(scriptId);
  40 + document.getElementsByTagName('head')[0].removeChild(script);
  41 + }
  42 +
  43 + function fetchJsonp(_url) {
  44 + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  45 +
  46 + // to avoid param reassign
  47 + var url = _url;
  48 + var timeout = options.timeout || defaultOptions.timeout;
  49 + var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
  50 +
  51 + var timeoutId = undefined;
  52 +
  53 + return new Promise(function (resolve, reject) {
  54 + var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
  55 + var scriptId = jsonpCallback + '_' + callbackFunction;
  56 +
  57 + window[callbackFunction] = function (response) {
  58 + resolve({
  59 + ok: true,
  60 + // keep consistent with fetch API
  61 + json: function json() {
  62 + return Promise.resolve(response);
  63 + }
  64 + });
  65 +
  66 + if (timeoutId) clearTimeout(timeoutId);
  67 +
  68 + removeScript(scriptId);
  69 +
  70 + clearFunction(callbackFunction);
  71 + };
  72 +
  73 + // Check if the user set their own params, and if not add a ? to start a list of params
  74 + url += url.indexOf('?') === -1 ? '?' : '&';
  75 +
  76 + var jsonpScript = document.createElement('script');
  77 + jsonpScript.setAttribute('src', '' + url + jsonpCallback + '=' + callbackFunction);
  78 + jsonpScript.id = scriptId;
  79 + document.getElementsByTagName('head')[0].appendChild(jsonpScript);
  80 +
  81 + timeoutId = setTimeout(function () {
  82 + reject(new Error('JSONP request to ' + _url + ' timed out'));
  83 +
  84 + clearFunction(callbackFunction);
  85 + removeScript(scriptId);
  86 + }, timeout);
  87 + });
  88 + }
  89 +
  90 + // export as global function
  91 + /*
  92 + let local;
  93 + if (typeof global !== 'undefined') {
  94 + local = global;
  95 + } else if (typeof self !== 'undefined') {
  96 + local = self;
  97 + } else {
  98 + try {
  99 + local = Function('return this')();
  100 + } catch (e) {
  101 + throw new Error('polyfill failed because global object is unavailable in this environment');
  102 + }
  103 + }
  104 + local.fetchJsonp = fetchJsonp;
  105 + */
  106 +
  107 + module.exports = fetchJsonp;
  108 +});
  1 +declare function fetchJsonp(url: string, options?: fetchJsonp.Options): Promise<fetchJsonp.Response>;
  2 +
  3 +declare namespace fetchJsonp {
  4 + interface Options {
  5 + timeout?: number;
  6 + jsonpCallback?: string;
  7 + jsonpCallbackFunction?: string;
  8 + }
  9 +
  10 + interface Response {
  11 + json(): Promise<any>;
  12 + json<T>(): Promise<T>;
  13 + ok: boolean;
  14 + }
  15 +}
  16 +
  17 +export = fetchJsonp;
  1 +{
  2 + "_args": [
  3 + [
  4 + "fetch-jsonp",
  5 + "D:\\work\\McuClient"
  6 + ]
  7 + ],
  8 + "_from": "fetch-jsonp@latest",
  9 + "_id": "fetch-jsonp@1.0.6",
  10 + "_inCache": true,
  11 + "_installable": true,
  12 + "_location": "/fetch-jsonp",
  13 + "_nodeVersion": "5.7.1",
  14 + "_npmOperationalInternal": {
  15 + "host": "packages-12-west.internal.npmjs.com",
  16 + "tmp": "tmp/fetch-jsonp-1.0.6.tgz_1486087842804_0.46444737794809043"
  17 + },
  18 + "_npmUser": {
  19 + "email": "neosoyn@gmail.com",
  20 + "name": "camsong"
  21 + },
  22 + "_npmVersion": "3.6.0",
  23 + "_phantomChildren": {},
  24 + "_requested": {
  25 + "name": "fetch-jsonp",
  26 + "raw": "fetch-jsonp",
  27 + "rawSpec": "",
  28 + "scope": null,
  29 + "spec": "latest",
  30 + "type": "tag"
  31 + },
  32 + "_requiredBy": [
  33 + "#USER"
  34 + ],
  35 + "_resolved": "https://registry.npmjs.org/fetch-jsonp/-/fetch-jsonp-1.0.6.tgz",
  36 + "_shasum": "8d2ae174ed14108292f025f43fa07d2078de6736",
  37 + "_shrinkwrap": null,
  38 + "_spec": "fetch-jsonp",
  39 + "_where": "D:\\work\\McuClient",
  40 + "author": {
  41 + "name": "Cam Song"
  42 + },
  43 + "bugs": {
  44 + "url": "https://github.com/camsong/fetch-jsonp/issues"
  45 + },
  46 + "dependencies": {},
  47 + "description": "Fetch JSONP like a boss using Fetch API",
  48 + "devDependencies": {
  49 + "babel": "^5.8.21",
  50 + "babel-core": "^5.8.21",
  51 + "babel-eslint": "^4.0.5",
  52 + "chai": "^3.2.0",
  53 + "eslint": "^1.1.0",
  54 + "eslint-config-airbnb": "^0.0.7",
  55 + "eslint-plugin-react": "^3.2.1",
  56 + "mocha": "^2.2.5"
  57 + },
  58 + "directories": {},
  59 + "dist": {
  60 + "shasum": "8d2ae174ed14108292f025f43fa07d2078de6736",
  61 + "tarball": "https://registry.npmjs.org/fetch-jsonp/-/fetch-jsonp-1.0.6.tgz"
  62 + },
  63 + "gitHead": "3b1be53776fa36a548fbf2aa16063c27ca318661",
  64 + "homepage": "https://github.com/camsong/fetch-jsonp#readme",
  65 + "keywords": [
  66 + "fetch",
  67 + "jsonp",
  68 + "github fetch",
  69 + "ajax"
  70 + ],
  71 + "license": "MIT",
  72 + "main": "build/fetch-jsonp.js",
  73 + "maintainers": [
  74 + {
  75 + "email": "neosoyn@gmail.com",
  76 + "name": "camsong"
  77 + }
  78 + ],
  79 + "name": "fetch-jsonp",
  80 + "optionalDependencies": {},
  81 + "readme": "ERROR: No README data found!",
  82 + "repository": {
  83 + "type": "git",
  84 + "url": "git+https://github.com/camsong/fetch-jsonp.git"
  85 + },
  86 + "scripts": {
  87 + "build": "babel src/ --modules umd --out-dir build",
  88 + "clean": "rm -rf build",
  89 + "lint": "eslint src/ test/",
  90 + "test": "mocha --compilers js:babel/register --recursive --ui bdd --reporter spec"
  91 + },
  92 + "version": "1.0.6"
  93 +}
  1 +# exclude all
  2 +/*
  3 +
  4 +# project structure
  5 +!/src/
  6 +!/etc/
  7 +!/doc/
  8 +!/test/
  9 +!/dist/
  10 +
  11 +# project files
  12 +!.gitignore
  13 +!README.md
  14 +!package.json
  15 +!LICENSE
  16 +!webpack.config.umd.js
  1 +iphunter
  2 +
  3 +to hunt a fatest http response.
  4 +
  5 +# usage
  6 +
  7 +iphunter(iplist,check_call_back[,timeout]);
  8 +
  9 +```javascript
  10 +
  11 +import iphunter from 'iphunter';
  12 +
  13 +iphunter([
  14 + '192.168.99.199',
  15 + 'baidu.com',
  16 + 'aliyun.com',
  17 + 'qq.com',
  18 + '192.168.99.100',
  19 + '127.0.0.0:8080',
  20 + '192.168.1.48:8080',
  21 + 'localhost:8080'
  22 +], function (fatest_ip_response) {
  23 + if(!fatest_ip_response) return console.error('nothing!');
  24 +
  25 + console.log('done -> ', fatest_ip_response);
  26 +},3000)
  27 +
  28 +```
  1 +<!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>
  1 +!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"))})()}])});
  1 +<!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>
  1 +!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__})()}])});
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta charset="UTF-8">
  5 + <title>UMD PLAYGROUND</title>
  6 +</head>
  7 +
  8 +<body>
  9 + <div id="stage"></div>
  10 +</body>
  11 +
  12 +</html>
  1 +{
  2 + "_args": [
  3 + [
  4 + "iphunter",
  5 + "D:\\work\\McuClient"
  6 + ]
  7 + ],
  8 + "_from": "iphunter@latest",
  9 + "_id": "iphunter@1.0.6",
  10 + "_inCache": true,
  11 + "_installable": true,
  12 + "_location": "/iphunter",
  13 + "_nodeVersion": "6.9.1",
  14 + "_npmOperationalInternal": {
  15 + "host": "packages-12-west.internal.npmjs.com",
  16 + "tmp": "tmp/iphunter-1.0.6.tgz_1488779370023_0.8911087329033762"
  17 + },
  18 + "_npmUser": {
  19 + "email": "1669499355@qq.com",
  20 + "name": "xinwangwang"
  21 + },
  22 + "_npmVersion": "3.10.8",
  23 + "_phantomChildren": {},
  24 + "_requested": {
  25 + "name": "iphunter",
  26 + "raw": "iphunter",
  27 + "rawSpec": "",
  28 + "scope": null,
  29 + "spec": "latest",
  30 + "type": "tag"
  31 + },
  32 + "_requiredBy": [
  33 + "#USER"
  34 + ],
  35 + "_resolved": "https://registry.npmjs.org/iphunter/-/iphunter-1.0.6.tgz",
  36 + "_shasum": "6b7559d73002bd8cc93d558a604d64518d180840",
  37 + "_shrinkwrap": null,
  38 + "_spec": "iphunter",
  39 + "_where": "D:\\work\\McuClient",
  40 + "author": {
  41 + "name": "AlexWang"
  42 + },
  43 + "dependencies": {},
  44 + "description": "to hunt a fatest http response.",
  45 + "devDependencies": {},
  46 + "directories": {
  47 + "doc": "doc",
  48 + "test": "test"
  49 + },
  50 + "dist": {
  51 + "shasum": "6b7559d73002bd8cc93d558a604d64518d180840",
  52 + "tarball": "https://registry.npmjs.org/iphunter/-/iphunter-1.0.6.tgz"
  53 + },
  54 + "gitHead": "c9958f825f514736bd0451f632c227db4bf0a7b7",
  55 + "keywords": [
  56 + "ipcheck"
  57 + ],
  58 + "license": "MIT",
  59 + "main": "dist/main.js",
  60 + "maintainers": [
  61 + {
  62 + "email": "1669499355@qq.com",
  63 + "name": "xinwangwang"
  64 + }
  65 + ],
  66 + "name": "iphunter",
  67 + "optionalDependencies": {},
  68 + "readme": "ERROR: No README data found!",
  69 + "scripts": {
  70 + "test": "test/index.js"
  71 + },
  72 + "version": "1.0.6",
  73 + "wbp": {
  74 + "build": "dist/",
  75 + "entries": {
  76 + "main": "./src/main.js",
  77 + "test": "./test/test.js"
  78 + },
  79 + "project": "umd",
  80 + "source": "src/"
  81 + }
  82 +}
  1 +class IpHunter {
  2 + constructor(ips, callback, timeout) {
  3 + this.ip = '';
  4 + this.ipcallback = callback;
  5 + this.timeoutId = null;
  6 + this.reqsCache = [];
  7 +
  8 + for (let i = 0; i < ips.length; i++) {
  9 + this.reqsCache.push(this.send(ips[i], timeout - 10));
  10 + }
  11 + this.timeoutId = setTimeout(this.notify.bind(this), timeout);
  12 + }
  13 +
  14 + clearAll() {
  15 + if (this.reqsCache && this.reqsCache.length) {
  16 + this.reqsCache.forEach((req) => {
  17 + req.abort();
  18 + })
  19 + }
  20 + clearTimeout(this.timeoutId);
  21 + this.ip = '';
  22 + this.ipcallback = null;
  23 + this.timeoutId = null;
  24 + this.reqsCache = [];
  25 + }
  26 +
  27 + clearReq(req) {
  28 + this.reqsCache.splice(this.reqsCache.indexOf(req), 1);
  29 + }
  30 +
  31 + notify() {
  32 + this.ipcallback(this.ip);
  33 + this.clearAll();
  34 + }
  35 +
  36 + send(pip, timeout) {
  37 + const req = new XMLHttpRequest();
  38 + req.open('HEAD', `//${pip}/?_=${Date.now()}`);
  39 + req.timeout = timeout;
  40 + req.onload = () => {
  41 + this.ip = pip;
  42 + this.clearReq(req);
  43 + req.onload = null;
  44 + this.notify();
  45 + }
  46 + req.ontimeout = () => {
  47 + this.clearReq(req);
  48 + req.ontimeout = null;
  49 + }
  50 + req.onerror = () => {
  51 + this.clearReq(req);
  52 + req.onerror = null;
  53 + }
  54 + req.onabort = () => {
  55 + this.clearReq(req);
  56 + req.onabort = null;
  57 + }
  58 + req.send();
  59 + return req
  60 + }
  61 +}
  62 +
  63 +/**
  64 + * ips check
  65 + * @param {array} ips
  66 + * @param {number} callback
  67 + * @return {null}
  68 + */
  69 +export default function check(ips, callback, timeout = 3000) {
  70 + if (!(ips && ips.length && callback)) throw new Error('ips and callback are required.');
  71 + new IpHunter(ips, callback, timeout);
  72 +}
  73 +
  1 +import check from 'main.js';
  2 +
  3 +check([
  4 + '192.168.99.199',
  5 + 'baidu.com',
  6 + 'aliyun.com',
  7 + 'qq.com',
  8 + '192.168.99.100',
  9 + '127.0.0.0:8080',
  10 + '192.168.1.48:8080',
  11 + 'localhost:8080'
  12 +], function (ip) {
  13 + console.log('done -> ', ip);
  14 +})
  15 +
  1 +module.exports = function (umdConf) {
  2 + umdConf.devServer.host = '0.0.0.0';
  3 + umdConf.webpackFeatures.enableEntryHTML();
  4 + umdConf.output.publicPath = '';
  5 +
  6 + if (umdConf.devMode) {
  7 + umdConf.webpackFeatures.enableEntryHot('test');
  8 + } else {
  9 + umdConf.webpackFeatures.enableUglifyJs({
  10 + comments: false
  11 + });
  12 + }
  13 + // console.log(umdConf);
  14 +};
  15 +
@@ -23,13 +23,13 @@ export default class Emiter { @@ -23,13 +23,13 @@ export default class Emiter {
23 } 23 }
24 } 24 }
25 } 25 }
26 - _emit(eid, data) { 26 + _emit(eid, data,data2) {
27 if (eid) { 27 if (eid) {
28 //eid=* broadcast 28 //eid=* broadcast
29 let asteriskStub =this.MAPS['*']; 29 let asteriskStub =this.MAPS['*'];
30 if (asteriskStub && asteriskStub.length) { 30 if (asteriskStub && asteriskStub.length) {
31 asteriskStub.forEach(function (elistener) { 31 asteriskStub.forEach(function (elistener) {
32 - elistener(eid, data); 32 + elistener(eid, data,data2);
33 }) 33 })
34 } 34 }
35 35
@@ -37,7 +37,7 @@ export default class Emiter { @@ -37,7 +37,7 @@ export default class Emiter {
37 let stub = this.MAPS[eid]; 37 let stub = this.MAPS[eid];
38 if (stub && stub.length) { 38 if (stub && stub.length) {
39 stub.forEach(function (elistener) { 39 stub.forEach(function (elistener) {
40 - elistener(data); 40 + elistener(data,data2);
41 }); 41 });
42 } 42 }
43 } 43 }
@@ -5,6 +5,9 @@ require('string.fromcodepoint'); @@ -5,6 +5,9 @@ require('string.fromcodepoint');
5 5
6 import Emiter from './Emiter'; 6 import Emiter from './Emiter';
7 import Sass from 'Sass'; 7 import Sass from 'Sass';
  8 +import ServerCheck from 'ServerCheck';
  9 +import RecordPlayBackParse from 'RecordPlayBackParse';
  10 +import MD5 from "md5";
8 import Mcu from 'mcu'; 11 import Mcu from 'mcu';
9 import MessageTypes from 'MessageTypes'; 12 import MessageTypes from 'MessageTypes';
10 import Loger from 'Loger'; 13 import Loger from 'Loger';
@@ -19,1014 +22,1128 @@ import GlobalConfig from 'GlobalConfig'; @@ -19,1014 +22,1128 @@ import GlobalConfig from 'GlobalConfig';
19 import ApeConsts from 'apes/ApeConsts'; 22 import ApeConsts from 'apes/ApeConsts';
20 import Base64 from 'base64-js'; 23 import Base64 from 'base64-js';
21 import ArrayBufferUtil from 'libs/ArrayBufferUtil'; 24 import ArrayBufferUtil from 'libs/ArrayBufferUtil';
  25 +
22 import UTF8 from 'utf-8'; 26 import UTF8 from 'utf-8';
23 27
24 let loger = Loger.getLoger('MessageEntrance'); 28 let loger = Loger.getLoger('MessageEntrance');
25 -let _sdkInfo={"version":"v.1.0.1","author":"www.3mang.com"}; 29 +let _sdkInfo = {"version": "v.1.8.0.20170314-1", "author": "www.3mang.com"};
26 30
27 //APE 31 //APE
28 let _sass; 32 let _sass;
29 -let _mcu ; 33 +let _serverCheck;
  34 +let _mcu;
30 let _confer_ape; 35 let _confer_ape;
31 let _chat_ape; 36 let _chat_ape;
32 let _video_ape; 37 let _video_ape;
33 let _audio_ape; 38 let _audio_ape;
34 let _doc_ape; 39 let _doc_ape;
35 let _whiteboard_ape; 40 let _whiteboard_ape;
36 -  
37 -////初始化成功回调函数  
38 -//let _initSuccessCallBackFun;  
39 -//  
40 -////加入会议成功回调函数  
41 -//let _joinClassSuccessCallBackFun;  
42 -//  
43 -////监听mcu所有错误异常回调函数  
44 -//let _mcuErrorCallBackFun; 41 +let _parseBuf;
45 42
46 //MCUClient 外部实例化主类 43 //MCUClient 外部实例化主类
47 export default class MessageEntrance extends Emiter { 44 export default class MessageEntrance extends Emiter {
48 - constructor() {  
49 - super();  
50 - //sdk 信息  
51 - this.sdkInfo = _sdkInfo;  
52 - loger.log(this.sdkInfo);  
53 -  
54 - //初始化状态  
55 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_0);  
56 -  
57 - //全局的Error处理  
58 - this.on(MessageTypes.MCU_ERROR, this._mcuErrorHandler.bind(this));  
59 -  
60 - // Sass平台层  
61 - _sass = Sass;  
62 - _sass.on('*', (type, data) => this._emit(type, data));  
63 - _sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5)  
64 - _sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this));//获取会议初始化信息  
65 - _sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取会议的基本信息  
66 - _sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this));//获取会议的最全信息和历史保存的数据  
67 - _sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this));//保存会议状态信息  
68 - _sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this));//保存会议录制信息  
69 - _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功  
70 -  
71 - // 底层MCU消息层  
72 - _mcu = Mcu;  
73 - _mcu.on('*', (type, data) => this._emit(type, data));  
74 - _mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this));//加入MCU会议完成  
75 -  
76 -  
77 - // 注册所有应用Ape  
78 - _confer_ape = new ConferApe();  
79 - _confer_ape.on('*', (type, data) => this._emit(type, data));  
80 - _confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件  
81 - _confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this));//当前会议状态信息发生改变  
82 - _confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this));//当前会议人员离开  
83 - _confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER,this._onClassNonentityRoster.bind(this));//当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在  
84 - _confer_ape.on(MessageTypes.CLASS_RECORD_START,this._onClassRecordStart.bind(this));//会议开始录制  
85 -  
86 -  
87 - _chat_ape = new ChatApe();  
88 - _chat_ape.on('*', (type, data) => this._emit(type, data));  
89 -  
90 - _video_ape = new VideoApe();  
91 - _video_ape.on('*', (type, data) => this._emit(type, data));  
92 - //_video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this));  
93 -  
94 - _audio_ape= new AudioApe();  
95 - _audio_ape.on('*', (type, data) => this._emit(type, data));  
96 - //_audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this));  
97 -  
98 - _whiteboard_ape = new WhiteBoardApe();  
99 - _whiteboard_ape.on('*', (type, data) => this._emit(type, data));  
100 - //_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this));  
101 -  
102 - _doc_ape = new DocApe();  
103 - _doc_ape.on('*', (type, data) => this._emit(type, data));  
104 - _doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this));  
105 - _doc_ape.on(MessageTypes.DOC_DELETE, this.docDeleteHandler.bind(this));  
106 - _doc_ape.on(DocApe.DOC_JOIN_CHANNEL_SUCCESS, this.docJoinChannelSuccess.bind(this));  
107 -  
108 -  
109 -  
110 - //公开外部调用的方法  
111 - //class  
112 - this.init = this._init.bind(this);  
113 - this.joinClass = this._joinClass.bind(this);  
114 - this.leaveClass = this._leaveClass.bind(this);  
115 - this.getMcuClientStatus = this._getMcuClientStatus.bind(this);  
116 - //this.getClassDetail = this._getClassDetail;//停用  
117 - this.getClassStatusInfo = this._getClassStatusInfo.bind(this);  
118 - this.sendStartClass = this._sendStartClass.bind(this);  
119 - this.sendPauseClass = this._sendPauseClass.bind(this);  
120 - this.sendCloseClass = this._sendCloseClass.bind(this);  
121 -  
122 -  
123 - //chatApe  
124 - this.sendChatMsg = this._sendChatMsg.bind(this);  
125 -  
126 - //videoApe  
127 - this.getVideoPlayPath = this._getVideoPlayPath.bind(this);  
128 - this.getVideoPublishPath = this._getVideoPublishPath.bind(this);  
129 - this.publishVideo = this._publishVideo.bind(this);  
130 - this.stopPublishVideo = this._stopPublishVideo.bind(this);  
131 - this.sendVideoBroadcastMsg=this._sendVideoBroadcastMsg.bind(this);  
132 -  
133 -  
134 - //audioApe  
135 - this.getAudioPlayPath = this._getPlayAudioPath.bind(this);  
136 - this.getAudioPublishPath = this._getPublishAudioPath.bind(this);  
137 - this.publishAudio = this._publishAudio.bind(this);  
138 - this.stopPublishAudio = this._stopPublishAudio.bind(this);  
139 - this.sendAudioBroadcastMsg=this.sendAudioCommandMsg.bind(this);  
140 -  
141 - //whiteBoradApe  
142 - this.sendInsertAnnotaion = this._sendInsertAnnotaion.bind(this);  
143 - //this.sendDeleteAnnotaion=this._sendDeleteAnnotaion;  
144 - this.sendDeleteAllAnnotation = this._sendDeleteAllAnnotation.bind(this);  
145 - this.sendDeleteCurPageAnnotation = this._sendDeleteCurPageAnnotation.bind(this);  
146 - this.sendGotoPrev = this._sendGotoPrev.bind(this); 45 + constructor() {
  46 + super();
  47 + //sdk 信息
  48 + this.sdkInfo = _sdkInfo;
  49 + loger.log(this.sdkInfo);
  50 +
  51 + //初始化状态
  52 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_0);
  53 +
  54 + //全局的Error处理
  55 + this.on(MessageTypes.MCU_ERROR, this._mcuErrorHandler.bind(this));
  56 +
  57 + // Sass平台层
  58 + _sass = Sass;
  59 + _sass.on('*', (type, data) => this._emit(type, data));
  60 + _sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5)
  61 + _sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this));//获取课堂初始化信息
  62 + //_sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取课堂的基本信息
  63 + _sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this));//获取课堂的最全信息和历史保存的数据
  64 +
  65 + _sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this));//保存课堂状态信息
  66 + _sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this));//保存课堂录制信息
  67 + _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功
  68 +
  69 + //ServerCheck ip
  70 + _serverCheck = ServerCheck;
  71 + _serverCheck.on(_serverCheck.SEVER_CHECK_BEST_IP_SUCCESS, this._serverCheckBestIpSuccessHandler.bind(this));//ip选点,获取最佳ip完成
  72 +
  73 +
  74 + // 底层MCU消息层
  75 + _mcu = Mcu;
  76 + _mcu.on('*', (type, data) => this._emit(type, data));
  77 + _mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this));//加入MCU课堂完成
  78 +
  79 + //录制回放
  80 + _parseBuf = RecordPlayBackParse;
  81 + _parseBuf.on('*', (type, data) => this._emit(type, data));
  82 + _parseBuf.on(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, this._joinRecordPlaybackSuccessHandler.bind(this));//加入录制回放完成
  83 +
  84 +
  85 + // 注册所有应用Ape
  86 + _confer_ape = new ConferApe();
  87 + _confer_ape.on('*', (type, data) => this._emit(type, data));
  88 + _confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件
  89 + _confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this));//当前课堂状态信息发生改变
  90 + _confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this));//当前课堂人员离开
  91 + _confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER, this._onClassNonentityRoster.bind(this));//当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在
  92 + _confer_ape.on(MessageTypes.CLASS_RECORD_START, this._onClassRecordStart.bind(this));//课堂开始录制
  93 +
  94 +
  95 + _chat_ape = new ChatApe();
  96 + _chat_ape.on('*', (type, data) => this._emit(type, data));
  97 +
  98 + _video_ape = new VideoApe();
  99 + _video_ape.on('*', (type, data) => this._emit(type, data));
  100 + _video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this));//这个监听事件不能删除,需要通知课堂模块,检查channel占用
  101 +
  102 +
  103 + _audio_ape = new AudioApe();
  104 + _audio_ape.on('*', (type, data) => this._emit(type, data));
  105 + _audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this));//这个监听事件不能删除,需要通知课堂模块,检查channel占用
  106 +
  107 + _whiteboard_ape = new WhiteBoardApe();
  108 + _whiteboard_ape.on('*', (type, data) => this._emit(type, data));
  109 + //_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this));
  110 +
  111 + _doc_ape = new DocApe();
  112 + _doc_ape.on('*', (type, data) => this._emit(type, data));
  113 + _doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this));
  114 + _doc_ape.on(MessageTypes.DOC_DELETE, this.docDeleteHandler.bind(this));
  115 + _doc_ape.on(DocApe.DOC_JOIN_CHANNEL_SUCCESS, this.docJoinChannelSuccess.bind(this));
  116 +
  117 + //公开外部调用的方法
  118 + //class
  119 + this.init = this._init.bind(this);
  120 + this.joinClass = this._joinClass.bind(this);
  121 + this.leaveClass = this._leaveClass.bind(this);
  122 + this.getMcuClientStatus = this._getMcuClientStatus.bind(this);
  123 + //this.getClassDetail = this._getClassDetail;//停用
  124 + this.getClassStatusInfo = this._getClassStatusInfo.bind(this);
  125 + this.sendStartClass = this._sendStartClass.bind(this);
  126 + this.sendPauseClass = this._sendPauseClass.bind(this);
  127 + this.sendCloseClass = this._sendCloseClass.bind(this);
  128 +
  129 + //录制回放
  130 + this.initRecordPlayback = this._initRecordPlayback.bind(this);
  131 + this.startRecordPlayback = this._startRecordPlayback.bind(this);
  132 + this.stopRecordPlayback = this._stopRecordPlayback.bind(this);
  133 + this.pauseRecordPlayback = this._pauseRecordPlayback.bind(this);
  134 + this.seekRecordPlayback = this._seekRecordPlayback.bind(this);
  135 +
  136 + //chatApe
  137 + this.sendChatMsg = this._sendChatMsg.bind(this);
  138 +
  139 + //videoApe
  140 + //this.getVideoPlayPath = this._getVideoPlayPath.bind(this);
  141 + this.getVideoPublishPath = this._getVideoPublishPath.bind(this);
  142 + this.getVideoAllChannelInfo = this._getVideoAllChannelInfo.bind(this);
  143 + this.publishVideo = this._publishVideo.bind(this);
  144 + this.stopPublishVideo = this._stopPublishVideo.bind(this);
  145 + this.sendVideoBroadcastMsg = this._sendVideoBroadcastMsg.bind(this);
  146 +
  147 +
  148 + //audioApe
  149 + //this.getAudioPlayPath = this._getPlayAudioPath.bind(this);
  150 + this.getAudioPublishPath = this._getPublishAudioPath.bind(this);
  151 + this.getAudioAllChannelInfo = this._getAudioAllChannelInfo.bind(this);
  152 + this.publishAudio = this._publishAudio.bind(this);
  153 + this.stopPublishAudio = this._stopPublishAudio.bind(this);
  154 + this.sendAudioBroadcastMsg = this.sendAudioCommandMsg.bind(this);
  155 +
  156 + //whiteBoradApe
  157 + this.sendInsertAnnotaion = this._sendInsertAnnotaion.bind(this);
  158 + //this.sendDeleteAnnotaion=this._sendDeleteAnnotaion;
  159 + this.sendDeleteAllAnnotation = this._sendDeleteAllAnnotation.bind(this);
  160 + this.sendDeleteCurPageAnnotation = this._sendDeleteCurPageAnnotation.bind(this);
  161 + this.sendGotoPrev = this._sendGotoPrev.bind(this);
  162 +
  163 + //DocApe
  164 + this.sendDocumentUpload = this._sendDocumentUpload.bind(this);//上传文档
  165 + this.sendDocumentSwitchDoc = this._sendDocumentSwitchDoc.bind(this); //切换文档
  166 + this.sendDocumentSwitchPage = this._sendDocumentSwitchPage.bind(this);//翻页
  167 + this.sendDocumentDelete = this._sassDeleteDocument.bind(this);
  168 + //删除文档,先通过Sass删除,sass删除成功之后再同步mcu
  169 + //this.sendDocumentDeleteAll= this._documentDeleteAll;//删除所有文档
  170 + this.sendDocumentCommand = this._sendDocumentCommand.bind(this);
  171 + //操作文档(翻页、缩放、滚动...)
  172 + this.getDocImageFullPath = this._getDocImageFullPath.bind(this);
  173 + //获取文档图片的完整路径
  174 + this.getDocPDFFullPath = this._getDocPDFFullPath.bind(this);//获取文档的完整路径
  175 +
  176 + }
  177 +
  178 + //mcu异常监听
  179 + _mcuErrorHandler(_data, _option) {
  180 + let option = _option || "";
  181 + let errorMessage = {"code": _data, "reson": MessageTypes.ErrorReson[_data] + " " + option};
  182 + loger.error("MCU_ERROR", errorMessage);
147 183
148 - //DocApe  
149 - this.sendDocumentUpload = this._sendDocumentUpload.bind(this);;//上传文档  
150 - this.sendDocumentSwitchDoc = this._sendDocumentSwitchDoc.bind(this);; //切换文档  
151 - this.sendDocumentSwitchPage = this._sendDocumentSwitchPage.bind(this);;//翻页  
152 - this.sendDocumentDelete = this._sassDeleteDocument.bind(this);;//删除文档,先通过Sass删除,sass删除成功之后再同步mcu  
153 - //this.sendDocumentDeleteAll= this._documentDeleteAll;//删除所有文档  
154 - this.sendDocumentCommand = this._sendDocumentCommand.bind(this);;//操作文档(翻页、缩放、滚动...)  
155 - this.getDocImageFullPath=this._getDocImageFullPath.bind(this);;//获取文档图片的完整路径  
156 - this.getDocPDFFullPath=this._getDocPDFFullPath.bind(this);;//获取文档的完整路径  
157 - }  
158 -  
159 -  
160 - //mcu异常监听  
161 - _mcuErrorHandler(_data, _option) {  
162 - let option = _option || "";  
163 - let errorMessage = {"code": _data, "reson": MessageTypes.ErrorReson[_data] + " " + option};  
164 - loger.error("MCU_ERROR", errorMessage);  
165 -  
166 - this._emit(MessageTypes.ERROR_EVENT,errorMessage);  
167 -  
168 -/* if (_mcuErrorCallBackFun) {  
169 - _mcuErrorCallBackFun(errorMessage);  
170 - }*/  
171 - }  
172 -  
173 - //获取当前的状态  
174 - _getMcuClientStatus() {  
175 - return GlobalConfig.getCurrentStatus();  
176 - }  
177 -  
178 -//获取会议信息  
179 - _getClassDetail() {  
180 - return GlobalConfig.getClassDetail();  
181 - }  
182 -  
183 - //获取当前会议的状态信息  
184 - _getClassStatusInfo(){  
185 - return GlobalConfig.classStatusInfo;  
186 - }  
187 - //关闭会议,所有人都退出  
188 - _doClassClose(_param) {  
189 - this._leaveClass();  
190 - }  
191 -  
192 - //离开会议,断开连接  
193 - _doClassExit() {  
194 - this._leaveClass();  
195 - }  
196 -  
197 - //当前的会议状态信息发生改变,需要保存会议状态到Sass  
198 - _onClassStatusInfoChange(_param) {  
199 - //如果MCU连接已经断开,不发送  
200 - if(GlobalConfig.getCurrentStatus().code!=GlobalConfig.statusCode_2.code){  
201 - loger.warn("不能保存会议状态",GlobalConfig.getCurrentStatus());  
202 - return;  
203 - }  
204 - this._sassSaveClassStatusInfo();  
205 - }  
206 -  
207 - //如果是第一次点击开始上课,需要创建录制时的文件名  
208 - _onClassRecordStart(_param){  
209 - if(GlobalConfig.getCurrentStatus().code!=GlobalConfig.statusCode_2.code){  
210 - loger.warn("不能保存会议状态",GlobalConfig.getCurrentStatus());  
211 - return;  
212 - }  
213 - if(_sass){  
214 - _sass.saveClassRecordContrlInfo(_param);  
215 - }  
216 - }  
217 -  
218 -  
219 - //有人员离开  
220 - _onClassDeleteRoster(_data){  
221 - //{"nodeId":nodeId}  
222 - //当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;  
223 - //只有自己是主持人的时候出才处理下面的事情  
224 - if(_data!=null&&_data.nodeId!=null&&GlobalConfig.isHost){  
225 - loger.log("有人员离开,检查一下离开的人员是否关闭推流");  
226 - if(_video_ape){  
227 - _video_ape.stopPublishVideo(_data);  
228 - }  
229 - if(_audio_ape){  
230 - _audio_ape.stopPublishAudio(_data);  
231 - }  
232 - }  
233 - }  
234 -  
235 - //当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel  
236 - //的占用状态导致,对于这种情况,需要释放掉  
237 - _onClassNonentityRoster(_param){  
238 - if(_param==null||_param.nodeId==null){  
239 - loger.warn("onClassNonentityRoster.参数错误")  
240 - return;  
241 - }  
242 - let data={"nodeId":_param.nodeId};  
243 - if(_video_ape){  
244 - _video_ape.stopPublishVideo(data);  
245 - }  
246 - if(_audio_ape){  
247 - _audio_ape.stopPublishAudio(data);  
248 - }  
249 - }  
250 -  
251 -  
252 - //Sass  
253 - //初始化  
254 - _init(_param) {  
255 - //{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}  
256 - //判断传入的参数是否存在  
257 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
258 - loger.error('init初始化失败,参数错误');  
259 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);  
260 - return;  
261 - }  
262 - //判断必要的参数字段值  
263 - if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {  
264 - loger.error('init初始化失败', _param);  
265 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);  
266 - return;  
267 - }  
268 - loger.log('init', _param);  
269 -  
270 - //保存参数  
271 - GlobalConfig.classId = parseInt(_param.classId);  
272 - GlobalConfig.portal = _param.portal;  
273 - GlobalConfig.userRole = _param.userRole || ApeConsts.normal;  
274 - GlobalConfig.userId = _param.userId || "0";  
275 - GlobalConfig.userName=_param.userName || "";  
276 -  
277 - //获取课堂校验信息  
278 - if (_sass) {  
279 - _sass.getJoinParams(GlobalConfig.getClassInfo());  
280 - }  
281 - }  
282 -  
283 - //外部请求加入会议  
284 - _joinClass(_param) {  
285 - //_joinClassSuccessCallBackFun = _onSuccess;  
286 - //{"userName":"名字","password":""}  
287 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
288 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);  
289 - loger.log('不能进入会议,传递的参数不对.', _param);  
290 - return;  
291 - }  
292 - //判断userName  
293 - if (_param.userName == null || _param.userName == "") {  
294 - loger.log('不能进入会议,传递的参数不对.名字不能为空');  
295 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);  
296 - return;  
297 - }  
298 -  
299 - if(GlobalConfig.userName==null||GlobalConfig.userName==""){  
300 - GlobalConfig.userName = _param.userName;  
301 - }  
302 - GlobalConfig.password = _param.password || "";  
303 - GlobalConfig.hasCamera=(typeof _param.hasCamera=="boolean")? _param.hasCamera:false;  
304 - GlobalConfig.hasMicrophone=(typeof _param.hasMicrophone=="boolean")? _param.hasMicrophone:false;  
305 - //debugger;  
306 - //开始校验  
307 - if (_sass) {  
308 - _sass.passwordAndMd5Checking(GlobalConfig.getClassInfo());  
309 - }  
310 - }  
311 -  
312 - // 用classId向SASS平台获取入会验证信息成功  
313 - _sassInitSuccessHandler(_data) {  
314 - //{"siteId":"h5test","passwordRequired":true,"md5":"de399d5540b3da2fbc1eb0a770d4fd66","code":0,"msType":1}  
315 - //储存数据  
316 - GlobalConfig.md5 = _data.md5 || "";//这个暂时用假数据,后台接口写完就有数据了  
317 - GlobalConfig.msType = _data.msType || 1;  
318 - GlobalConfig.siteId = _data.siteId || "";  
319 - GlobalConfig.classType = _data.meetingType || 0;  
320 -  
321 - //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的  
322 - GlobalConfig.passwordRequired = _data.passwordRequired || false;//md5验证的时候需要Sass返回的值,不能更改  
323 -  
324 - loger.log('SASS平台获取入会验证信息成功.');  
325 -  
326 - //设置当前的会议状态  
327 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_1);  
328 - //返回给客户端初始化成功的数据  
329 - let initSuccessCallBackData = {};  
330 - initSuccessCallBackData.siteId = GlobalConfig.siteId;  
331 - initSuccessCallBackData.classId = GlobalConfig.classId;  
332 - initSuccessCallBackData.userRole = GlobalConfig.userRole;  
333 - initSuccessCallBackData.userId = GlobalConfig.userId;  
334 - initSuccessCallBackData.classType = GlobalConfig.classType;  
335 -  
336 - //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的  
337 - if (GlobalConfig.userRole== ApeConsts.host) {  
338 - initSuccessCallBackData.passwordRequired =true;  
339 - } else {  
340 - initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;  
341 - }  
342 -  
343 - this._emit(MessageTypes.CLASS_INIT_SUCCESS,initSuccessCallBackData);  
344 -  
345 -/* if (_initSuccessCallBackFun) {  
346 - _initSuccessCallBackFun(initSuccessCallBackData);  
347 - }*/  
348 -  
349 - }  
350 -  
351 - // 通过SASS平台验证(密码和MD5)  
352 - _sassJoinSuccessHandler(_data) {  
353 - //返回值  
354 - /* flag 数值型 无 True:成功  
355 - Flag:失败  
356 - h5_mcu_list 字符串 H5muc列表  
357 - maxVideoChannels 数值型 最大视频路数  
358 - maxAudioChannels 数值型 最大音频路数  
359 - h5Module 数值型 H5开关  
360 - ms 字符串 Ms列表  
361 - mcu 字符串 Mcu列表  
362 - rs 字符串 Rs列表  
363 - doc 字符串 Doc列表*/  
364 -  
365 - /* {  
366 - "record": "112.126.80.182:80",  
367 - "flag": "true",  
368 - "h5Module": 1,  
369 - "maxVideoChannels": 1,  
370 - "mcu": "123.56.73.119:7000;123.56.69.230:7000;112.126.80.182:7000",  
371 - "ms": "pubms.3mang.com:1935",  
372 - "doc": "101.200.150.192:80",  
373 - "rs": "pubms.3mang.com:1935",  
374 - "type": 1,  
375 - "maxAudioChannels": 1,  
376 - "h5_mcu_list": "123.56.73.119:7001;123.56.69.230:7001;112.126.80.182:7001"  
377 - }*/  
378 -  
379 - /*  
380 - if (_data.h5_mcu_list) {  
381 - //MCU地址默认使用第一个  
382 - let server = _data.h5_mcu_list.split(";")[0];  
383 - GlobalConfig.MCUServerIP = server.split(":")[0];  
384 - GlobalConfig.MCUServerPort = server.split(":")[1];  
385 - }  
386 -  
387 - //视频推流播流地址  
388 - if (_data.ms) {  
389 - //MS地址默认使用第一个  
390 - let server = _data.ms.split(";")[0];  
391 - GlobalConfig.MSServerIP = server.split(":")[0];  
392 - GlobalConfig.MSServerPort = server.split(":")[1];  
393 - }  
394 -  
395 - //m3u8播流地址  
396 - if(_data.rs){  
397 - //RS地址默认使用第一个  
398 - let server = _data.rs.split(";")[0];  
399 - GlobalConfig.RSServerIP = server.split(":")[0];  
400 - GlobalConfig.RSServerPort = server.split(":")[1];  
401 - }  
402 -  
403 - GlobalConfig.docServer = _data.doc;  
404 - GlobalConfig.h5_mcu_list = _data.h5_mcu_list;  
405 - GlobalConfig.h5Module = _data.h5Module;  
406 - GlobalConfig.mcu = _data.mcu;  
407 - GlobalConfig.ms = _data.ms;  
408 - GlobalConfig.record = _data.record;  
409 - GlobalConfig.rs = _data.rs;  
410 - GlobalConfig.maxVideoChannels = _data.maxVideoChannels;  
411 - GlobalConfig.maxAudioChannels = _data.maxAudioChannels;  
412 -  
413 - */  
414 -  
415 -  
416 - /*  
417 - //这个接口获取的数据在getClassParam接口的数据中都有,内容重复,这个接口废弃  
418 - //获取会议基本信息  
419 - if (_sass) {  
420 - _sass.getClassDetail();  
421 - }  
422 - */  
423 -  
424 - //获取会议最完整的数据  
425 - if (_sass) {  
426 - _sass.getClassParam();  
427 - }  
428 - }  
429 -  
430 - //获取会议基本信息getClassH5  
431 - _sassGetClassDetailSuccessHandler(_data) {  
432 - loger.log('获取getClassDetail完成.');  
433 - /* {  
434 - "cycle": 0,  
435 - "repeatmonthweekweek": 0,  
436 - "status": 1,  
437 - "repeatmonthday": 0,  
438 - "repeatmode": 0,  
439 - "beginTime": "2017-02-03 09:00:00",  
440 - "frequency": 1,  
441 - "endmode": 0,  
442 - "meetingContent": "",  
443 - "endTime": "2017-03-31 11:00:00",  
444 - "repeatweek": "",  
445 - "category": "",  
446 - "finalenddate": "",  
447 - "repeatday": 0,  
448 - "meetingName": "mcu1",  
449 - "errorCode": 0,  
450 - "monthType": 0,  
451 - "repeatmonthweekday": 0,  
452 - "endcount": 1  
453 - }*/  
454 - GlobalConfig.classDetail = _data;  
455 - GlobalConfig.className = _data.meetingName || "";  
456 - GlobalConfig.classBeginTime = _data.beginTime || "";  
457 - GlobalConfig.classEndTime = _data.endTime || "";  
458 -  
459 - //获取会议所有信息和以前保存的会议状态信息(最全的信息)  
460 - if (_sass) {  
461 - _sass.getClassParam();  
462 - }  
463 - }  
464 -  
465 - //获取会议所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do  
466 - _sassGetClassParamSuccessHandler(_data) {  
467 - //console.log(GlobalConfig.classStatusInfo)  
468 - loger.log('获取课堂会议的完整信息完成.');  
469 - // console.log(_data);  
470 - //包含整个会议最全的信息,储存数据  
471 - if (_data) {  
472 - GlobalConfig.className = _data.meetingName || "";  
473 - GlobalConfig.classBeginTime = _data.beginTime || "";  
474 - GlobalConfig.classEndTime = _data.endTime || "";  
475 -  
476 - GlobalConfig.maxVideoChannels = _data.maxVideoChannels;  
477 - GlobalConfig.maxAudioChannels = _data.maxAudioChannels;  
478 -  
479 - GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表  
480 - GlobalConfig.setRecordList(_data.recordList);//录制回放地址  
481 - GlobalConfig.setDocList(_data.docList);//文档地址  
482 - GlobalConfig.setMsList(_data.msList);//推流播流服务器地址  
483 - GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址  
484 - GlobalConfig.setMcuList(_data.mcuList);//mcu  
485 - GlobalConfig.setMusicList(_data.musicList);//  
486 - GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表  
487 -  
488 -  
489 - if (_data.mcuList) {  
490 - //MCU地址默认使用第一个  
491 - GlobalConfig.MCUServerIP =_data.mcuList[0].ip||"";  
492 - GlobalConfig.MCUServerPort =_data.mcuList[0].port||"";  
493 - }  
494 -  
495 - //视频推流播流地址  
496 - if (_data.msList) {  
497 - //MS地址默认使用第一个  
498 - GlobalConfig.MSServerIP =_data.msList[0].ip||"";  
499 - GlobalConfig.MSServerPort =_data.msList[0].port||"";  
500 - }  
501 -  
502 - //m3u8播流地址  
503 - if(_data.rsList){  
504 - //RS地址默认使用第一个  
505 - GlobalConfig.RSServerIP =_data.rsList[0].ip||"";  
506 - GlobalConfig.RSServerPort =_data.rsList[0].port||"";  
507 - }  
508 -  
509 - //文档地址  
510 - if(_data.docList){  
511 - //doc地址默认使用第一个  
512 - GlobalConfig.DOCServerIP =_data.docList[0].ip||"";  
513 - GlobalConfig.DOCServerPort =_data.docList[0].port||"";  
514 - }  
515 -  
516 - //record  
517 - if(_data.recordList){  
518 - //地址默认使用第一个  
519 - GlobalConfig.RecordServerIP =_data.recordList[0].ip||"";  
520 - GlobalConfig.RecordServerPort =_data.recordList[0].port||"";  
521 - }  
522 -  
523 - }  
524 -  
525 - if (_data.currentInfo) {  
526 - //根据从Sass获取的数据信息,同步最后一次保存的会议状态信息  
527 - loger.log("同步最后一次保存过的会议状态信息");  
528 - GlobalConfig.setClassStatusInfo(_data.currentInfo);  
529 - console.log(GlobalConfig.classStatusInfo);  
530 - } else {  
531 - loger.log("还没有保存过会议状信息");  
532 - }  
533 -  
534 - //所有Sass流程完成,开始MCU连接  
535 - this._joinMCU();  
536 - }  
537 -  
538 - //保存会议状态信息  
539 - _sassSaveClassStatusInfo() {  
540 - if (GlobalConfig.isHost) {  
541 - //只有加入会议之后才能保存数据  
542 - if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {  
543 - //POST 保存数据  
544 - _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo});//保存会议状态信息  
545 - } else {  
546 - loger.error("不能保存会议数据", GlobalConfig.getCurrentStatus());  
547 - }  
548 - } else {  
549 - loger.log("没有保存会议状态信息的权限 isHost", GlobalConfig.isHost);  
550 - }  
551 - }  
552 -  
553 - //保存会态信息成功  
554 - _sassSaveClassStatusInfoSuccessHandler(_data) {  
555 - loger.log('保存会议状态信息成功.');  
556 - console.log(_data);  
557 - }  
558 - _sassSaveClassRecordInfoSuccessHandler(_data){  
559 - loger.log('保存会议录制信息成功.');  
560 - console.log(_data);  
561 - }  
562 -  
563 - //Sass校验流程结束之后,开始加入MCU  
564 - _joinMCU() {  
565 - loger.log('加入底层MCU会议.');  
566 - if (_mcu) {  
567 - _mcu.joinMCU(GlobalConfig.getClassInfo());  
568 - }  
569 - }  
570 -  
571 - // MCU 会议成功  
572 - _mcuJoinMCUClassSuccessHandler(_data) {  
573 - loger.log('MCU 会议成功.');  
574 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);  
575 -  
576 - //返回给客户端初始化成功的数据  
577 - let initSuccessCallBackData = {};  
578 -  
579 - initSuccessCallBackData.DOCServerIP =GlobalConfig.DOCServerIP;  
580 - initSuccessCallBackData.DOCServerPort =GlobalConfig.DOCServerPort;  
581 -  
582 - initSuccessCallBackData.classId = GlobalConfig.classId;  
583 - initSuccessCallBackData.className = GlobalConfig.className;  
584 - initSuccessCallBackData.h5Module = GlobalConfig.h5Module;  
585 - initSuccessCallBackData.isHost = GlobalConfig.isHost;  
586 - initSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;  
587 - initSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;  
588 - initSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;  
589 -  
590 - initSuccessCallBackData.msType = GlobalConfig.msType;  
591 - initSuccessCallBackData.nodeId = GlobalConfig.nodeId;  
592 - initSuccessCallBackData.password = GlobalConfig.password;  
593 - initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true  
594 - //GlobalConfig.passwordRequired 老师的默认是true  
595 - //GlobalConfig.portal=_data.portal;  
596 - initSuccessCallBackData.role = GlobalConfig.role;  
597 - initSuccessCallBackData.siteId = GlobalConfig.siteId;  
598 - initSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;  
599 - initSuccessCallBackData.userId = GlobalConfig.userId;  
600 - initSuccessCallBackData.userName = GlobalConfig.userName;  
601 - initSuccessCallBackData.userRole = GlobalConfig.userRole;  
602 - initSuccessCallBackData.userType = GlobalConfig.userType;  
603 -  
604 - initSuccessCallBackData.siteId = GlobalConfig.siteId;  
605 - initSuccessCallBackData.classId = GlobalConfig.classId;  
606 - initSuccessCallBackData.userRole = GlobalConfig.userRole;  
607 - initSuccessCallBackData.userId = GlobalConfig.userId;  
608 - initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;  
609 - initSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;  
610 - loger.log('加入会议成功');  
611 - console.log(initSuccessCallBackData);  
612 -  
613 - //加入会议成功,广播消息  
614 - this._emit(MessageTypes.CLASS_JOIN_SUCCESS,initSuccessCallBackData);  
615 -  
616 -/* //返回给客户数据  
617 - if (_joinClassSuccessCallBackFun) {  
618 - _joinClassSuccessCallBackFun(initSuccessCallBackData);  
619 - }*/  
620 - }  
621 -  
622 - //Sass删除文档数据  
623 - _sassDeleteDocument(_param) {  
624 - if(!_mcu.connected){  
625 - loger.warn(GlobalConfig.getCurrentStatus());  
626 - return;  
627 - }  
628 -  
629 - //判断传入的参数是否存在  
630 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
631 - loger.error('sassDeleteDocument失败,参数错误', _param);  
632 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);  
633 - return;  
634 - }  
635 - //判断必要的参数字段值  
636 - if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.docId == null || _param.docId == "") {  
637 - loger.error('sassDeleteDocument失败', _param);  
638 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);  
639 - return;  
640 - }  
641 - loger.log('_sassDeleteDocument', _param);  
642 -  
643 - if (_sass) {  
644 - _sass.sassDeleteDocument(_param);  
645 - }  
646 - }  
647 -  
648 - //Sass删除文档成功之后,同步删除MCU数据  
649 - _sassDeleteDocumentSuccess(_param) {  
650 - loger.log('sassDeleteDocumentSuccess', _param);  
651 - this._sendDocumentDelete(_param);  
652 - }  
653 -  
654 - //ConferApe  
655 - //开始上课  
656 - _sendStartClass(_param){  
657 - if(!_mcu.connected){  
658 - loger.warn(GlobalConfig.getCurrentStatus());  
659 - return;  
660 - }  
661 -  
662 - if(_confer_ape){  
663 - _confer_ape.startClass(_param);  
664 - }  
665 - }  
666 - //暂停上课  
667 - _sendPauseClass(_param){  
668 - if(!_mcu.connected){  
669 - loger.warn(GlobalConfig.getCurrentStatus());  
670 - return;  
671 - }  
672 - if(_confer_ape){  
673 - _confer_ape.pauseClass(_param);  
674 - }  
675 - }  
676 - //停止上课  
677 - _sendCloseClass(_param){  
678 - if(!_mcu.connected){  
679 - loger.warn(GlobalConfig.getCurrentStatus());  
680 - return;  
681 - }  
682 - if(_confer_ape){  
683 - _confer_ape.closeClass(_param);  
684 - }  
685 - }  
686 - // 离开会议  
687 - _leaveClass() {  
688 - if(!_mcu.connected){  
689 - loger.warn(GlobalConfig.getCurrentStatus());  
690 - return;  
691 - }  
692 -  
693 - //停止推流  
694 - if(_video_ape){  
695 - _video_ape.stopPublishVideo(); 184 + this._emit(MessageTypes.ERROR_EVENT, errorMessage);
  185 +
  186 + /* if (_mcuErrorCallBackFun) {
  187 + _mcuErrorCallBackFun(errorMessage);
  188 + }*/
  189 + }
  190 +
  191 + //获取当前的状态
  192 + _getMcuClientStatus() {
  193 + return GlobalConfig.getCurrentStatus();
  194 + }
  195 +
  196 +//获取课堂信息
  197 + _getClassDetail() {
  198 + return GlobalConfig.getClassDetail();
  199 + }
  200 +
  201 + //获取当前课堂的状态信息
  202 + _getClassStatusInfo() {
  203 + return GlobalConfig.classStatusInfo;
  204 + }
  205 +
  206 + //关闭课堂,所有人都退出
  207 + _doClassClose(_param) {
  208 + this._leaveClass();
  209 + }
  210 +
  211 + //离开课堂,断开连接
  212 + _doClassExit() {
  213 + this._leaveClass();
  214 + }
  215 +
  216 + //当前的课堂状态信息发生改变,需要保存课堂状态到Sass
  217 + _onClassStatusInfoChange(_param) {
  218 + //如果MCU连接已经断开,不发送
  219 + if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {
  220 + loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
  221 + return;
  222 + }
  223 + this._sassSaveClassStatusInfo();
  224 + }
  225 +
  226 + //如果是第一次点击开始上课,需要创建录制时的文件名
  227 + _onClassRecordStart(_param) {
  228 + if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {
  229 + loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
  230 + return;
  231 + }
  232 + if (_sass) {
  233 + _sass.saveClassRecordContrlInfo(_param);
  234 + }
  235 + }
  236 +
  237 +
  238 + //有人员离开
  239 + _onClassDeleteRoster(_data) {
  240 +
  241 + //在conferApe中做处理,这里不需要再处理
  242 + //{"nodeId":nodeId}
  243 + //当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;
  244 + /* if(_data!=null&&_data.nodeId!=null){
  245 + loger.log("有人员离开,检查一下离开的人员是否关闭推流");
  246 + if(_video_ape){
  247 + _video_ape.stopPublishVideo(_data);
  248 + }
  249 + if(_audio_ape){
  250 + _audio_ape.stopPublishAudio(_data);
  251 + }
  252 + }*/
  253 + }
  254 +
  255 + //当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
  256 + //的占用状态导致,对于这种情况,需要释放掉
  257 + _onClassNonentityRoster(_param) {
  258 + if(GlobalConfig.isRecordPlayBack){
  259 + loger.warn("录制回放中,不处理")
  260 + return;
  261 + }
  262 +
  263 + if (_param == null || _param.nodeId == null) {
  264 + loger.warn("onClassNonentityRoster.参数错误")
  265 + return;
  266 + }
  267 + let data = {"nodeId": _param.nodeId};
  268 + if (_video_ape) {
  269 + _video_ape.stopPublishVideo(data);
  270 + }
  271 + if (_audio_ape) {
  272 + _audio_ape.stopPublishAudio(data);
  273 + }
  274 + }
  275 +
  276 +
  277 + //Sass
  278 + //初始化
  279 + _init(_param) {
  280 + //{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}
  281 + //判断传入的参数是否存在
  282 + if (_param == null || EngineUtils.isEmptyObject(_param)) {
  283 + loger.error('init初始化失败,参数错误');
  284 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);
  285 + return;
  286 + }
  287 + //判断必要的参数字段值
  288 + if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {
  289 + loger.error('init初始化失败', _param);
  290 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);
  291 + return;
  292 + }
  293 + loger.log('init', _param);
  294 +
  295 + //保存参数
  296 + GlobalConfig.isRecordPlayBack=false;//设置为非录制回放状态
  297 + GlobalConfig.classId = parseInt(_param.classId);
  298 + GlobalConfig.portal = _param.portal;
  299 + GlobalConfig.userRole = _param.userRole || ApeConsts.normal;
  300 + GlobalConfig.userId = _param.userId || "0";
  301 + GlobalConfig.userName = _param.userName || "";
  302 +
  303 + //最长允许录制的时间
  304 + if(_param.allowRecordMaxTime){
  305 + GlobalConfig.allowRecordMaxTime=parseInt(_param.allowRecordMaxTime);
  306 + }
  307 +
  308 + //获取课堂校验信息
  309 + if (_sass) {
  310 + _sass.getJoinParams(GlobalConfig.getClassInfo());
  311 + }
  312 + }
  313 +
  314 + //外部请求加入课堂
  315 + _joinClass(_param) {
  316 + //_joinClassSuccessCallBackFun = _onSuccess;
  317 + //{"userName":"名字","password":""}
  318 + if (_param == null || EngineUtils.isEmptyObject(_param)) {
  319 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
  320 + loger.log('不能进入课堂,传递的参数不对.', _param);
  321 + return;
  322 + }
  323 + //判断userName
  324 + if (_param.userName == null || _param.userName == "") {
  325 + loger.log('不能进入课堂,传递的参数不对.名字不能为空');
  326 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
  327 + return;
  328 + }
  329 +
  330 + if (GlobalConfig.userName == null || GlobalConfig.userName == "") {
  331 + GlobalConfig.userName = _param.userName;
  332 + }
  333 + GlobalConfig.autoLogin=_param.autoLogin||"";
  334 + GlobalConfig.password = _param.password || "";
  335 + GlobalConfig.hasCamera = (typeof _param.hasCamera == "boolean") ? _param.hasCamera : false;
  336 + GlobalConfig.hasMicrophone = (typeof _param.hasMicrophone == "boolean") ? _param.hasMicrophone : false;
  337 +
  338 + loger.log("autoLoginMd5",GlobalConfig.classId,GlobalConfig.userId,GlobalConfig.userRole);
  339 + let autoLoginMd5=MD5(""+GlobalConfig.classId+GlobalConfig.userId+GlobalConfig.userRole);
  340 + loger.log("joinClass-GlobalConfig.autoLogin",GlobalConfig.autoLogin,"autoLoginMd5-",autoLoginMd5);
  341 + if(GlobalConfig.autoLogin&&autoLoginMd5==GlobalConfig.autoLogin){
  342 + // MD5(classId+userId+userRole)==m
  343 + //自动登录,跳过验证流程
  344 + loger.log("自动登录");
  345 + this._sassJoinSuccessHandler();
  346 + }else {
  347 + //不能自动登录,开始校验
  348 + if (_sass) {
  349 + _sass.passwordAndMd5Checking(GlobalConfig.getClassInfo());
  350 + }
  351 + }
  352 + }
  353 +
  354 + // 用classId向SASS平台获取入会验证信息成功
  355 + _sassInitSuccessHandler(_data) {
  356 + //{"siteId":"h5test","passwordRequired":true,"md5":"de399d5540b3da2fbc1eb0a770d4fd66","code":0,"msType":1}
  357 + //储存数据
  358 + GlobalConfig.md5 = _data.md5 || "";//这个暂时用假数据,后台接口写完就有数据了
  359 + GlobalConfig.msType = _data.msType || 1;
  360 + GlobalConfig.siteId = _data.siteId || "";
  361 + GlobalConfig.classType = _data.meetingType || 0;
  362 +
  363 + //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
  364 + GlobalConfig.passwordRequired = _data.passwordRequired || false;//md5验证的时候需要Sass返回的值,不能更改
  365 +
  366 + loger.log('SASS平台获取入会验证信息成功.');
  367 +
  368 + //设置当前的课堂状态
  369 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_1);
  370 + //返回给客户端初始化成功的数据
  371 + let initSuccessCallBackData = {};
  372 + initSuccessCallBackData.siteId = GlobalConfig.siteId;
  373 + initSuccessCallBackData.classId = GlobalConfig.classId;
  374 + initSuccessCallBackData.userRole = GlobalConfig.userRole;
  375 + initSuccessCallBackData.userId = GlobalConfig.userId;
  376 + initSuccessCallBackData.userName = GlobalConfig.userName;
  377 + initSuccessCallBackData.classType = GlobalConfig.classType;
  378 +
  379 + //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
  380 + if (GlobalConfig.userRole == ApeConsts.host) {
  381 + initSuccessCallBackData.passwordRequired = true;
  382 + } else {
  383 + initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
  384 + }
  385 +
  386 + this._emit(MessageTypes.CLASS_INIT_SUCCESS, initSuccessCallBackData);
  387 + }
  388 +
  389 + // 通过SASS平台验证(密码和MD5)
  390 + _sassJoinSuccessHandler(_data) {
  391 + //返回值
  392 + /* flag 数值型 无 True:成功
  393 + Flag:失败
  394 + h5_mcu_list 字符串 H5muc列表
  395 + maxVideoChannels 数值型 最大视频路数
  396 + maxAudioChannels 数值型 最大音频路数
  397 + h5Module 数值型 H5开关
  398 + ms 字符串 Ms列表
  399 + mcu 字符串 Mcu列表
  400 + rs 字符串 Rs列表
  401 + doc 字符串 Doc列表*/
  402 + //获取课堂最完整的数据
  403 + if (_sass) {
  404 + _sass.getClassParam();
  405 + }
  406 + }
  407 +
  408 + //获取课堂所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do
  409 + _sassGetClassParamSuccessHandler(_data) {
  410 + //console.log(GlobalConfig.classStatusInfo)
  411 + loger.log('获取课堂课堂的完整信息完成.');
  412 + // console.log(_data);
  413 + //包含整个课堂最全的信息,储存数据
  414 + if (_data) {
  415 + GlobalConfig.mcuDelay = _data.mcuDelay || 60;//mcu消息延迟,用于文档模块
  416 + GlobalConfig.className = _data.meetingName || "";
  417 + GlobalConfig.classBeginTime = _data.beginTime || "";
  418 + GlobalConfig.classEndTime = _data.endTime || "";
  419 + GlobalConfig.userIp = _data.userIp || "";
  420 +
  421 + GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
  422 + GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
  423 +
  424 + GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表
  425 + GlobalConfig.setRecordList(_data.recordList);//录制回放地址
  426 + GlobalConfig.setDocList(_data.docList);//文档地址
  427 + GlobalConfig.setMsList(_data.msList);//推流播流服务器地址
  428 + GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址
  429 + GlobalConfig.setMcuList(_data.mcuList);//mcu
  430 + GlobalConfig.setMusicList(_data.musicList);//
  431 + GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表
  432 +
  433 +
  434 + if (_data.mcuList&&_data.mcuList.length>0) {
  435 + //MCU地址默认使用第一个
  436 + GlobalConfig.MCUServerIP = _data.mcuList[0].ip || "";
  437 + GlobalConfig.MCUServerPort = _data.mcuList[0].port || "";
  438 + }
  439 +
  440 + //上课中视频推流播流地址
  441 + if (_data.msList&&_data.msList.length>0) {
  442 + //MS地址默认使用第一个
  443 + GlobalConfig.MSServerIP = _data.msList[0].ip || "";
  444 + GlobalConfig.MSServerPort = _data.msList[0].port || "";
  445 + }
  446 +
  447 + //录制回放时m3u8播流地址
  448 + if (_data.rsList&&_data.rsList.length>0) {
  449 + //RS地址默认使用第一个
  450 + GlobalConfig.RSServerIP = _data.rsList[0].ip || "";
  451 + GlobalConfig.RSServerPort = _data.rsList[0].port || "";
  452 + }
  453 +
  454 + //文档地址
  455 + if (_data.docList&&_data.docList.length>0) {
  456 + //doc地址默认使用第一个
  457 + GlobalConfig.DOCServerIP = _data.docList[0].ip || "";
  458 + GlobalConfig.DOCServerPort = _data.docList[0].port || "";
  459 + }
  460 +
  461 + //record
  462 + if (_data.recordList&&_data.recordList.length>0) {
  463 + //地址默认使用第一个
  464 + GlobalConfig.RecordServerIP = _data.recordList[0].ip || "";
  465 + GlobalConfig.RecordServerPort = _data.recordList[0].port || "";
  466 + }
  467 +
  468 + }
  469 +
  470 + if (_data.currentInfo) {
  471 + //根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息
  472 + loger.log("本地同步最后一次保存过的课堂状态信息");
  473 + try {
  474 + GlobalConfig.setClassStatusInfo(JSON.parse(_data.currentInfo));
  475 + }catch (err){
  476 + GlobalConfig.setClassStatusInfo(_data.currentInfo);
  477 + }
  478 + loger.log(GlobalConfig.classStatusInfo);
  479 + } else {
  480 + loger.log("还没有保存过课堂状信息");
  481 + }
  482 +
  483 +
  484 + //录制回放不需要选点
  485 + if(GlobalConfig.isRecordPlayBack){
  486 + if (_parseBuf) {
  487 + //开启录制回放流程
  488 + loger.log("开启录制回放流程");
  489 + _parseBuf.readyRecordPlay();
  490 + }else {
  491 + loger.warn("开启录制回放流程失败,还未创建模块");
  492 + }
  493 + }else {
  494 + //根据用户的userIp获取信息
  495 + this.getUserIpInfo();
  496 + }
  497 + }
  498 +
  499 + //根据UserIp获取ip信息
  500 + getUserIpInfo() {
  501 + if (_serverCheck) {
  502 + _serverCheck.getUserIpInfo("", GlobalConfig.userIp);
  503 + }
  504 + }
  505 +
  506 + //MCU MS ip选点完成,开加入MCU
  507 + _serverCheckBestIpSuccessHandler(_data) {
  508 + loger.log("_serverCheckBestIpSuccessHandler,IP选点结束");
  509 + this._joinMCU();
  510 + }
  511 +
  512 + //保存课堂状态信息
  513 + _sassSaveClassStatusInfo() {
  514 + if (GlobalConfig.isHost) {
  515 + //只有加入课堂之后才能保存数据
  516 + if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
  517 + //POST 保存数据
  518 + _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo});//保存课堂状态信息
  519 + } else {
  520 + loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());
  521 + }
  522 + } else {
  523 + loger.log("没有保存课堂状态信息的权限 isHost", GlobalConfig.isHost);
  524 + }
  525 + }
  526 +
  527 + //保存会态信息成功
  528 + _sassSaveClassStatusInfoSuccessHandler(_data) {
  529 + loger.log('保存课堂状态信息成功.');
  530 + loger.log(_data);
  531 + }
  532 +
  533 + _sassSaveClassRecordInfoSuccessHandler(_data) {
  534 + loger.log('保存课堂录制信息成功.');
  535 + loger.log(_data);
  536 + }
  537 +
  538 + //Sass校验流程结束之后,开始加入MCU
  539 + _joinMCU() {
  540 + loger.log('加入底层MCU课堂.');
  541 + if (_mcu) {
  542 + _mcu.joinMCU(GlobalConfig.getClassInfo());
  543 + }
  544 + }
  545 +
  546 + // MCU 课堂成功
  547 + _mcuJoinMCUClassSuccessHandler(_data) {
  548 + loger.log('MCU 课堂成功.');
  549 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
  550 +
  551 + //返回给客户端初始化成功的数据
  552 + let joinClassSuccessCallBackData = {};
  553 +
  554 + joinClassSuccessCallBackData.isRecordPlayBack=GlobalConfig.isRecordPlayBack;
  555 +
  556 + joinClassSuccessCallBackData.DOCServerIP = GlobalConfig.DOCServerIP;
  557 + joinClassSuccessCallBackData.DOCServerPort = GlobalConfig.DOCServerPort;
  558 +
  559 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  560 + joinClassSuccessCallBackData.className = GlobalConfig.className;
  561 + joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;
  562 + joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;
  563 + joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
  564 + joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
  565 + joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
  566 +
  567 + joinClassSuccessCallBackData.msType = GlobalConfig.msType;
  568 + joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;
  569 + joinClassSuccessCallBackData.password = GlobalConfig.password;
  570 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
  571 + //GlobalConfig.passwordRequired 老师的默认是true
  572 + //GlobalConfig.portal=_data.portal;
  573 + joinClassSuccessCallBackData.role = GlobalConfig.role;
  574 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  575 + joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
  576 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  577 + joinClassSuccessCallBackData.userName = GlobalConfig.userName;
  578 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  579 + joinClassSuccessCallBackData.userType = GlobalConfig.userType;
  580 +
  581 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  582 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  583 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  584 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  585 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
  586 + joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
  587 +
  588 + joinClassSuccessCallBackData.country = GlobalConfig.country;//国家
  589 + joinClassSuccessCallBackData.city = GlobalConfig.city;//城市
  590 + joinClassSuccessCallBackData.province = GlobalConfig.province;//服务商
  591 + joinClassSuccessCallBackData.isp = GlobalConfig.isp;//服务商
  592 +
  593 + joinClassSuccessCallBackData.classTimestamp=GlobalConfig.classTimestamp;//课堂进行的累积时间
  594 + joinClassSuccessCallBackData.recordPlaybackMaxTime=GlobalConfig.recordPlaybackMaxTime;//录制回放的总时间
  595 + loger.log('加入课堂成功');
  596 + loger.log(joinClassSuccessCallBackData);
  597 +
  598 + //加入课堂成功,广播消息
  599 + this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);
  600 + }
  601 +
  602 + //Sass删除文档数据
  603 + _sassDeleteDocument(_param) {
  604 + if (!_mcu.connected) {
  605 + loger.warn(GlobalConfig.getCurrentStatus());
  606 + return;
  607 + }
  608 +
  609 + //判断传入的参数是否存在
  610 + if (_param == null || EngineUtils.isEmptyObject(_param)) {
  611 + loger.error('sassDeleteDocument失败,参数错误', _param);
  612 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);
  613 + return;
  614 + }
  615 + //判断必要的参数字段值
  616 + if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.docId == null || _param.docId == "") {
  617 + loger.error('sassDeleteDocument失败', _param);
  618 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);
  619 + return;
  620 + }
  621 + loger.log('_sassDeleteDocument', _param);
  622 +
  623 + if (_sass) {
  624 + _sass.sassDeleteDocument(_param);
  625 + }
  626 + }
  627 +
  628 + //Sass删除文档成功之后,同步删除MCU数据
  629 + _sassDeleteDocumentSuccess(_param) {
  630 + loger.log('sassDeleteDocumentSuccess', _param);
  631 + this._sendDocumentDelete(_param);
  632 + }
  633 +
  634 + //ConferApe
  635 + //开始上课
  636 + _sendStartClass(_param) {
  637 + if (!_mcu.connected) {
  638 + loger.warn(GlobalConfig.getCurrentStatus());
  639 + return;
  640 + }
  641 +
  642 + if (_confer_ape) {
  643 + _confer_ape.startClass(_param);
  644 + }
  645 + }
  646 +
  647 + //暂停上课
  648 + _sendPauseClass(_param) {
  649 + if (!_mcu.connected) {
  650 + loger.warn(GlobalConfig.getCurrentStatus());
  651 + return;
  652 + }
  653 + if (_confer_ape) {
  654 + _confer_ape.pauseClass(_param);
  655 + }
  656 + }
  657 +
  658 + //停止上课
  659 + _sendCloseClass(_param) {
  660 + if (!_mcu.connected) {
  661 + loger.warn(GlobalConfig.getCurrentStatus());
  662 + return;
  663 + }
  664 + if (_confer_ape) {
  665 + _confer_ape.closeClass(_param);
  666 + }
  667 + }
  668 +
  669 + // 离开课堂
  670 + _leaveClass() {
  671 + if (!_mcu.connected) {
  672 + loger.warn(GlobalConfig.getCurrentStatus());
  673 + return;
  674 + }
  675 +
  676 + //停止推流
  677 + if (_video_ape) {
  678 + _video_ape.stopPublishVideo();
  679 + }
  680 + if (_audio_ape) {
  681 + _audio_ape.stopPublishAudio();
  682 + }
  683 + //离开课堂
  684 + if (_confer_ape) {
  685 + _confer_ape.stopRecord();
  686 + _confer_ape.leaveClass();
  687 + }
  688 + //断开MCU连接
  689 + if (_mcu) {
  690 + _mcu.leaveMCU();
  691 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3);
  692 + }
696 } 693 }
697 - if(_audio_ape){  
698 - _audio_ape.stopPublishAudio(); 694 +
  695 +
  696 + //ChatApe
  697 + // 发送聊天消息
  698 + _sendChatMsg(_messageInfo) {
  699 + if (!_mcu.connected) {
  700 + loger.warn(GlobalConfig.getCurrentStatus());
  701 + return;
  702 + }
  703 + if (_messageInfo === null || EngineUtils.isEmptyObject(_messageInfo)) {
  704 + loger.log('sendChatMsg 传递的参数不对', _messageInfo);
  705 + return;
  706 + }
  707 + if (_chat_ape) {
  708 + _chat_ape.sendChatMsg(_messageInfo);
  709 + }
699 } 710 }
700 - //离开会议  
701 - if(_confer_ape){  
702 - _confer_ape.stopRecord();  
703 - _confer_ape.leaveClass(); 711 +
  712 + //VidoeApe
  713 + videoUpdate(_data) {
  714 + //视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
  715 + if (_confer_ape) {
  716 + _confer_ape.updaterRosterStatus(_data);
  717 + }
704 } 718 }
705 - //断开MCU连接  
706 - if(_mcu){  
707 - _mcu.leaveMCU();  
708 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3); 719 +
  720 + _sendVideoBroadcastMsg(_param) {
  721 + if (!_mcu.connected) {
  722 + loger.warn(GlobalConfig.getCurrentStatus());
  723 + return;
  724 + }
  725 + if (_video_ape) {
  726 + return _video_ape.sendVideoBroadcastMsg(_param);
  727 + }
709 } 728 }
710 - }  
711 729
  730 + _getVideoPlayPath(_param) {
  731 + if (_video_ape) {
  732 + return _video_ape.getPlayVideoPath(_param);
  733 + }
  734 + }
712 735
713 - //ChatApe  
714 - // 发送聊天消息  
715 - _sendChatMsg(_messageInfo) {  
716 - if(!_mcu.connected){  
717 - loger.warn(GlobalConfig.getCurrentStatus());  
718 - return; 736 + _getVideoPublishPath(_param) {
  737 + if (_video_ape) {
  738 + return _video_ape.getPublishVideoPath(_param);
  739 + }
719 } 740 }
720 - if(_messageInfo===null||EngineUtils.isEmptyObject(_messageInfo)){  
721 - loger.log('sendChatMsg 传递的参数不对',_messageInfo);  
722 - return ; 741 +
  742 + _getVideoAllChannelInfo(_param) {
  743 + if (_video_ape) {
  744 + return _video_ape.getAllChannelInfo(_param);
  745 + }
723 } 746 }
724 - if (_chat_ape) {  
725 - _chat_ape.sendChatMsg(_messageInfo); 747 +
  748 + _publishVideo(_param) {
  749 + if (!_mcu.connected) {
  750 + loger.warn(GlobalConfig.getCurrentStatus());
  751 + return;
  752 + }
  753 + if (_video_ape) {
  754 + return _video_ape.publishVideo(_param);
  755 + }
726 } 756 }
727 - }  
728 757
729 - //VidoeApe  
730 - videoUpdate(_data){  
731 - //视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态  
732 - if(_confer_ape){  
733 - _confer_ape.updaterRosterStatus(_data); 758 + _stopPublishVideo(_param) {
  759 + if (!_mcu.connected) {
  760 + loger.warn(GlobalConfig.getCurrentStatus());
  761 + return;
  762 + }
  763 + if (_video_ape) {
  764 + return _video_ape.stopPublishVideo(_param);
  765 + }
734 } 766 }
735 - }  
736 767
737 - _sendVideoBroadcastMsg(_param){  
738 - if(!_mcu.connected){  
739 - loger.warn(GlobalConfig.getCurrentStatus());  
740 - return; 768 + //AudioApe
  769 + audioUpdate(_data) {
  770 + //音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
  771 + if (_confer_ape) {
  772 + _confer_ape.updaterRosterStatus(_data);
  773 + }
741 } 774 }
742 - if(_video_ape){  
743 - return _video_ape.sendVideoBroadcastMsg(_param); 775 +
  776 + sendAudioCommandMsg(_param) {
  777 + if (!_mcu.connected) {
  778 + loger.warn(GlobalConfig.getCurrentStatus());
  779 + return;
  780 + }
  781 + if (_audio_ape) {
  782 + return _audio_ape.sendAudioBroadcastMsg(_param);
  783 + }
  784 + }
  785 +
  786 + _getPlayAudioPath(_param) {
  787 + if (_audio_ape) {
  788 + return _audio_ape.getAudioPlayPath(_param);
  789 + }
  790 + }
  791 +
  792 + _getPublishAudioPath(_param) {
  793 + if (_audio_ape) {
  794 + return _audio_ape.getAudioPublishPath(_param);
  795 + }
  796 + }
  797 +
  798 + _getAudioAllChannelInfo(_param) {
  799 + if (_audio_ape) {
  800 + return _audio_ape.getAllChannelInfo(_param);
  801 + }
744 } 802 }
745 - }  
746 803
747 - _getVideoPlayPath(_param){  
748 - if(_video_ape){  
749 - return _video_ape.getPlayVideoPath(_param); 804 + _publishAudio(_param) {
  805 + if (!_mcu.connected) {
  806 + loger.warn(GlobalConfig.getCurrentStatus());
  807 + return;
  808 + }
  809 + if (_audio_ape) {
  810 + return _audio_ape.publishAudio(_param);
  811 + }
750 } 812 }
751 - }  
752 813
753 - _getVideoPublishPath(_param){  
754 - if(_video_ape){  
755 - return _video_ape.getPublishVideoPath(_param); 814 + _stopPublishAudio(_param) {
  815 + if (!_mcu.connected) {
  816 + loger.warn(GlobalConfig.getCurrentStatus());
  817 + return;
  818 + }
  819 + if (_audio_ape) {
  820 + return _audio_ape.stopPublishAudio(_param);
  821 + }
756 } 822 }
757 - }  
758 823
759 - _publishVideo(_param){  
760 - if(!_mcu.connected){  
761 - loger.warn(GlobalConfig.getCurrentStatus());  
762 - return; 824 +
  825 + //WhiteBoardApe
  826 + // 添加标注,发送信息
  827 + _sendInsertAnnotaion(_param) {
  828 + if (!_mcu.connected) {
  829 + loger.warn(GlobalConfig.getCurrentStatus());
  830 + return;
  831 + }
  832 + if (_whiteboard_ape) {
  833 + _whiteboard_ape.sendInsetAnnotaion(_param);
  834 + }
  835 + }
  836 +
  837 + //删除标注,发送信息
  838 + _sendDeleteAnnotaion(_param) {
  839 + if (!_mcu.connected) {
  840 + loger.warn(GlobalConfig.getCurrentStatus());
  841 + return;
  842 + }
  843 + if (_whiteboard_ape) {
  844 + _whiteboard_ape.sendDeleteAnnotaion(_param);
  845 + }
763 } 846 }
764 - if(_video_ape){  
765 - return _video_ape.publishVideo(_param); 847 +
  848 + //删除当前页面上的所有标注
  849 + _sendDeleteCurPageAnnotation(_param) {
  850 + if (!_mcu.connected) {
  851 + loger.warn(GlobalConfig.getCurrentStatus());
  852 + return;
  853 + }
  854 + if (_whiteboard_ape) {
  855 + _whiteboard_ape.sendDeleteCurPageAnnotation(_param);
  856 + }
766 } 857 }
767 - }  
768 858
769 - _stopPublishVideo(_param){  
770 - if(!_mcu.connected){  
771 - loger.warn(GlobalConfig.getCurrentStatus());  
772 - return; 859 + //删除所有标注
  860 + _sendDeleteAllAnnotation(_param) {
  861 + if (!_mcu.connected) {
  862 + loger.warn(GlobalConfig.getCurrentStatus());
  863 + return;
  864 + }
  865 + if (_whiteboard_ape) {
  866 + _whiteboard_ape.sendDeleteAllAnnotation(_param);
  867 + }
773 } 868 }
774 - if(_video_ape){  
775 - return _video_ape.stopPublishVideo(_param); 869 +
  870 + //返回上一步标注
  871 + _sendGotoPrev(_param) {
  872 + if (_whiteboard_ape) {
  873 + _whiteboard_ape.sendGotoPrev(_param);
  874 + }
776 } 875 }
777 - }  
778 876
779 - //AudioApe  
780 - audioUpdate(_data){  
781 - //音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态  
782 - if(_confer_ape){  
783 - _confer_ape.updaterRosterStatus(_data); 877 +
  878 + //DocApe
  879 + //获取文档完整路径
  880 + _getDocImageFullPath(_param) {
  881 + if (_doc_ape) {
  882 + return _doc_ape.getDocImageFullPath(_param);
  883 + } else {
  884 + loger.error("文档模块还没有创建,无法获取");
  885 + return [];
  886 + }
784 } 887 }
785 - }  
786 888
787 - sendAudioCommandMsg(_param){  
788 - if(!_mcu.connected){  
789 - loger.warn(GlobalConfig.getCurrentStatus());  
790 - return; 889 + _getDocPDFFullPath(_param) {
  890 + if (_doc_ape) {
  891 + return _doc_ape.getDocPDFFullPath(_param);
  892 + } else {
  893 + loger.error("文档模块还没有创建,无法获取");
  894 + return [];
  895 + }
791 } 896 }
792 - if(_audio_ape){  
793 - return _audio_ape.sendAudioBroadcastMsg(_param); 897 +
  898 + //上传文档
  899 + _sendDocumentUpload(_param) {
  900 + if (!_mcu.connected) {
  901 + loger.warn(GlobalConfig.getCurrentStatus());
  902 + return;
  903 + }
  904 + if (_doc_ape) {
  905 + _doc_ape.documentUpload(_param);
  906 + }
794 } 907 }
795 - }  
796 908
797 - _getPlayAudioPath(_param){  
798 - if(_audio_ape){  
799 - return _audio_ape.getAudioPlayPath(_param); 909 + //切换文档
  910 + _sendDocumentSwitchDoc(_param) {
  911 + if (!_mcu.connected) {
  912 + loger.warn(GlobalConfig.getCurrentStatus());
  913 + return;
  914 + }
  915 + if (_doc_ape) {
  916 + _doc_ape.documentSwitchDoc(_param);
  917 + }
800 } 918 }
801 - }  
802 919
803 - _getPublishAudioPath(_param){  
804 - if(_audio_ape){  
805 - return _audio_ape.getAudioPublishPath(_param); 920 + //操作文档(翻页)
  921 + _sendDocumentSwitchPage(_param) {
  922 + if (!_mcu.connected) {
  923 + loger.warn(GlobalConfig.getCurrentStatus());
  924 + return;
  925 + }
  926 + if (_doc_ape) {
  927 + _doc_ape.documentSwitchPage(_param);
  928 + }
806 } 929 }
807 - }  
808 930
809 - _publishAudio(_param){  
810 - if(!_mcu.connected){  
811 - loger.warn(GlobalConfig.getCurrentStatus());  
812 - return; 931 + //操作文档(缩放、滚动...)
  932 + _sendDocumentCommand(_param) {
  933 + if (!_mcu.connected) {
  934 + loger.warn(GlobalConfig.getCurrentStatus());
  935 + return;
  936 + }
  937 + if (_doc_ape) {
  938 + _doc_ape.documentCommand(_param);
  939 + }
813 } 940 }
814 - if(_audio_ape){  
815 - return _audio_ape.publishAudio(_param); 941 +
  942 + //删除文档
  943 + _sendDocumentDelete(_param) {
  944 + if (!_mcu.connected) {
  945 + loger.warn(GlobalConfig.getCurrentStatus());
  946 + return;
  947 + }
  948 + if (_doc_ape) {
  949 + _doc_ape.documentDelete(_param);
  950 + }
816 } 951 }
817 - }  
818 952
819 - _stopPublishAudio(_param){  
820 - if(!_mcu.connected){  
821 - loger.warn(GlobalConfig.getCurrentStatus());  
822 - return; 953 + //删除所有文档
  954 + _documentDeleteAll(_param) {
  955 + if (!_mcu.connected) {
  956 + loger.warn(GlobalConfig.getCurrentStatus());
  957 + return;
  958 + }
  959 + if (_doc_ape) {
  960 + _doc_ape.documentDeleteAll(_param);
  961 + }
823 } 962 }
824 - if(_audio_ape){  
825 - return _audio_ape.stopPublishAudio(_param); 963 +
  964 + //// 文档变更,白板也需要做处理
  965 + docUpdateHandler(_data) {
  966 + if (!_mcu.connected) {
  967 + loger.warn(GlobalConfig.getCurrentStatus());
  968 + return;
  969 + }
  970 + loger.log('Doc UpdateId ->');
  971 + loger.log(_data);
  972 + if (_whiteboard_ape) {
  973 + _whiteboard_ape.docUpdateHandler(_data);
  974 + }
826 } 975 }
827 - }  
828 976
  977 + //文档删除,白板也需要做处理
  978 + docDeleteHandler(_data) {
  979 + if (_whiteboard_ape) {
  980 + _whiteboard_ape.docDeleteHandler(_data);
  981 + }
  982 + }
829 983
830 - //WhiteBoardApe  
831 - // 添加标注,发送信息  
832 - _sendInsertAnnotaion(_param){  
833 - if(!_mcu.connected){  
834 - loger.warn(GlobalConfig.getCurrentStatus());  
835 - return; 984 + //文档加入频道成功,同步到MCU服务器上的数据
  985 + docJoinChannelSuccess() {
  986 + loger.log("docJoinChannelSuccess isHost=", GlobalConfig.isHost);
  987 + loger.log(GlobalConfig.docListPrepare);
  988 + loger.log("docJoinChannelSuccess docListPrepare=");
  989 + //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传
  990 + if (GlobalConfig.isHost) {
  991 + for (let value of GlobalConfig.docListPrepare) {
  992 + if (value) {
  993 + /* //提前上传的文档文档信息的结构
  994 + {
  995 + "MD5": "f3feb3fac8cd3a953bded00e07a0c66b",
  996 + "absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
  997 + "createUserID": "972",
  998 + "createUserIP": "114.241.81.175",
  999 + "createUserName": "base",
  1000 + "dynamicPPT": 0,
  1001 + "dynamicTransferStatic": "",
  1002 + "id": "8ab3b0ed5a00f2fa015a0219a3df016c",
  1003 + "meetingNumber": "",
  1004 + "name": "McuClient_v.1.0.1_API.pdf",
  1005 + "orderStr": "",
  1006 + "pdfSize": 5,
  1007 + "processEndTime": "2017-02-03 11:54:31",
  1008 + "processRate": 0,
  1009 + "processStartTime": "2017-02-03 11:54:27",
  1010 + "relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
  1011 + "siteID": "h5test",
  1012 + "size": 360920,
  1013 + "status": 3,
  1014 + "type": "pdf",
  1015 + "uploadEndTime": "2017-02-03 11:54:27",
  1016 + "uploadStartTime": "2017-02-03 11:54:27"
  1017 + }*/
  1018 +
  1019 + loger.log("判断是否需要把提前上传的文档上传到mcu", value);
  1020 + let paramInfo = {
  1021 + "pageNum": value.pdfSize,
  1022 + "fileName": value.name,
  1023 + "fileType": value.type,
  1024 + "relativeUrl": value.relativeLocation,
  1025 + "url": value.absoluteLocation,
  1026 + "creatUserId": value.createUserID,
  1027 + "docId": value.id,
  1028 + "md5": value.MD5,
  1029 + "visible": false
  1030 + };
  1031 +
  1032 + this._sendDocumentUpload(paramInfo);
  1033 + }
  1034 + }
  1035 + }
836 } 1036 }
837 - if(_whiteboard_ape){  
838 - _whiteboard_ape.sendInsetAnnotaion(_param); 1037 +
  1038 + //录制回放相关的处理------------------------------------------------
  1039 + //录制回放初始化
  1040 + _initRecordPlayback(_param){
  1041 + //{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}
  1042 + if (_param == null) {
  1043 + loger.error('录制回放初始化失败,参数错误');
  1044 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED);
  1045 + return;
  1046 + }
  1047 + //判断必要的参数字段值
  1048 + if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {
  1049 + loger.error('录制回放初始化失败', _param);
  1050 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED);
  1051 + return;
  1052 + }
  1053 + loger.log('录制回放', _param);
  1054 +
  1055 + //保存参数
  1056 + GlobalConfig.isRecordPlayBack=true;//设置为录制回放状态
  1057 + GlobalConfig.classId = parseInt(_param.classId);
  1058 + GlobalConfig.portal = _param.portal;
  1059 + GlobalConfig.userRole =ApeConsts.normal;//*************很重要,录制回放的时候,身份模式是普通人********
  1060 + GlobalConfig.userId = _param.userId || "0";
  1061 + GlobalConfig.userName = _param.userName || "";
  1062 +
  1063 + //获取课堂最完整的数据,录制回放需要获取课堂数据
  1064 + if (_sass) {
  1065 + _sass.getClassParam();
  1066 + }
839 } 1067 }
840 - }  
841 1068
842 - //删除标注,发送信息  
843 - _sendDeleteAnnotaion(_param){  
844 - if(!_mcu.connected){  
845 - loger.warn(GlobalConfig.getCurrentStatus());  
846 - return; 1069 + //开始录制回放
  1070 + _startRecordPlayback(_param) {
  1071 + if (_parseBuf) {
  1072 + _parseBuf.startRecordPlayback(_param);
  1073 + }
847 } 1074 }
848 - if(_whiteboard_ape){  
849 - _whiteboard_ape.sendDeleteAnnotaion(_param); 1075 + //停止录制回放
  1076 + _stopRecordPlayback(_param) {
  1077 + if (_parseBuf) {
  1078 + _parseBuf.stopRecordPlayback(_param);
  1079 + }
  1080 + }
  1081 + //暂停录制回放
  1082 + _pauseRecordPlayback(_param) {
  1083 + if (_parseBuf) {
  1084 + _parseBuf.pauseRecordPlayback(_param);
  1085 + }
850 } 1086 }
851 - }  
852 - //删除当前页面上的所有标注  
853 - _sendDeleteCurPageAnnotation(_param){  
854 - if(!_mcu.connected){  
855 - loger.warn(GlobalConfig.getCurrentStatus());  
856 - return;  
857 - }  
858 - if(_whiteboard_ape){  
859 - _whiteboard_ape.sendDeleteCurPageAnnotation(_param);  
860 - }  
861 - }  
862 - //删除所有标注  
863 - _sendDeleteAllAnnotation(_param){  
864 - if(!_mcu.connected){  
865 - loger.warn(GlobalConfig.getCurrentStatus());  
866 - return;  
867 - }  
868 - if(_whiteboard_ape){  
869 - _whiteboard_ape.sendDeleteAllAnnotation(_param);  
870 - }  
871 - }  
872 - //返回上一步标注  
873 - _sendGotoPrev(_param){  
874 - if(_whiteboard_ape){  
875 - _whiteboard_ape.sendGotoPrev(_param);  
876 - }  
877 - }  
878 -  
879 -  
880 - //DocApe  
881 - //获取文档完整路径  
882 - _getDocImageFullPath(_param){  
883 - if(_doc_ape){  
884 - return _doc_ape.getDocImageFullPath(_param);  
885 - }else {  
886 - loger.error("文档模块还没有创建,无法获取");  
887 - return [];  
888 - }  
889 - }  
890 - _getDocPDFFullPath(_param){  
891 - if(_doc_ape){  
892 - return _doc_ape.getDocPDFFullPath(_param);  
893 - }else {  
894 - loger.error("文档模块还没有创建,无法获取");  
895 - return [];  
896 - }  
897 - }  
898 - //上传文档  
899 - _sendDocumentUpload(_param){  
900 - if(!_mcu.connected){  
901 - loger.warn(GlobalConfig.getCurrentStatus());  
902 - return;  
903 - }  
904 - if(_doc_ape){  
905 - _doc_ape.documentUpload(_param);  
906 - }  
907 - }  
908 - //切换文档  
909 - _sendDocumentSwitchDoc(_param){  
910 - if(!_mcu.connected){  
911 - loger.warn(GlobalConfig.getCurrentStatus());  
912 - return;  
913 - }  
914 - if(_doc_ape){  
915 - _doc_ape.documentSwitchDoc(_param);  
916 - }  
917 - }  
918 - //操作文档(翻页)  
919 - _sendDocumentSwitchPage(_param){  
920 - if(!_mcu.connected){  
921 - loger.warn(GlobalConfig.getCurrentStatus());  
922 - return;  
923 - }  
924 - if(_doc_ape){  
925 - _doc_ape.documentSwitchPage(_param);  
926 - }  
927 - }  
928 - //操作文档(缩放、滚动...)  
929 - _sendDocumentCommand(_param){  
930 - if(!_mcu.connected){  
931 - loger.warn(GlobalConfig.getCurrentStatus());  
932 - return;  
933 - }  
934 - if(_doc_ape){  
935 - _doc_ape.documentCommand(_param);  
936 - }  
937 - }  
938 - //删除文档  
939 - _sendDocumentDelete(_param){  
940 - if(!_mcu.connected){  
941 - loger.warn(GlobalConfig.getCurrentStatus());  
942 - return;  
943 - }  
944 - if(_doc_ape){  
945 - _doc_ape.documentDelete(_param);  
946 - }  
947 - }  
948 - //删除所有文档  
949 - _documentDeleteAll(_param){  
950 - if(!_mcu.connected){  
951 - loger.warn(GlobalConfig.getCurrentStatus());  
952 - return;  
953 - }  
954 - if(_doc_ape){  
955 - _doc_ape.documentDeleteAll(_param);  
956 - }  
957 - }  
958 -  
959 - //// 文档变更,白板也需要做处理  
960 - docUpdateHandler(_data) {  
961 - if(!_mcu.connected){  
962 - loger.warn(GlobalConfig.getCurrentStatus());  
963 - return;  
964 - }  
965 - loger.log('Doc UpdateId ->');  
966 - console.log(_data);  
967 - if(_whiteboard_ape){  
968 - _whiteboard_ape.docUpdateHandler(_data);  
969 - }  
970 - }  
971 -  
972 - //文档删除,白板也需要做处理  
973 - docDeleteHandler(_data){  
974 - if(_whiteboard_ape){  
975 - _whiteboard_ape.docDeleteHandler(_data);  
976 - }  
977 - }  
978 -  
979 - //文档加入频道成功,同步到MCU服务器上的数据  
980 - docJoinChannelSuccess(){  
981 - loger.log("docJoinChannelSuccess isHost=",GlobalConfig.isHost);  
982 - console.log(GlobalConfig.docListPrepare);  
983 - loger.log("docJoinChannelSuccess docListPrepare=");  
984 - //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传  
985 - if(GlobalConfig.isHost){  
986 - for (let value of GlobalConfig.docListPrepare){  
987 - if(value){  
988 - /* //提前上传的文档文档信息的结构  
989 - {  
990 - "MD5": "f3feb3fac8cd3a953bded00e07a0c66b",  
991 - "absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",  
992 - "createUserID": "972",  
993 - "createUserIP": "114.241.81.175",  
994 - "createUserName": "base",  
995 - "dynamicPPT": 0,  
996 - "dynamicTransferStatic": "",  
997 - "id": "8ab3b0ed5a00f2fa015a0219a3df016c",  
998 - "meetingNumber": "",  
999 - "name": "McuClient_v.1.0.1_API.pdf",  
1000 - "orderStr": "",  
1001 - "pdfSize": 5,  
1002 - "processEndTime": "2017-02-03 11:54:31",  
1003 - "processRate": 0,  
1004 - "processStartTime": "2017-02-03 11:54:27",  
1005 - "relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",  
1006 - "siteID": "h5test",  
1007 - "size": 360920,  
1008 - "status": 3,  
1009 - "type": "pdf",  
1010 - "uploadEndTime": "2017-02-03 11:54:27",  
1011 - "uploadStartTime": "2017-02-03 11:54:27"  
1012 - }*/  
1013 -  
1014 - loger.log("判断是否需要把提前上传的文档上传到mcu",value);  
1015 - let paramInfo={  
1016 - "pageNum": value.pdfSize,  
1017 - "fileName": value.name,  
1018 - "fileType": value.type,  
1019 - "relativeUrl": value.relativeLocation,  
1020 - "url": value.absoluteLocation,  
1021 - "creatUserId":value.createUserID,  
1022 - "docId": value.id,  
1023 - "md5":value.MD5,  
1024 - "visible": false  
1025 - };  
1026 -  
1027 - this._sendDocumentUpload(paramInfo);  
1028 - }  
1029 - }  
1030 - }  
1031 - } 1087 + //seek录制回放
  1088 + _seekRecordPlayback(_param) {
  1089 + if (_parseBuf) {
  1090 + _parseBuf.seekRecordPlayback(_param);
  1091 + }
  1092 + }
  1093 +
  1094 + //录制回放加入 课堂成功
  1095 + _joinRecordPlaybackSuccessHandler(_data) {
  1096 + loger.log('加入录制回放成功.');
  1097 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
  1098 +
  1099 + //返回给客户端初始化成功的数据
  1100 + let joinClassSuccessCallBackData = {};
  1101 +
  1102 + joinClassSuccessCallBackData.isRecordPlayBack=GlobalConfig.isRecordPlayBack;
  1103 +
  1104 + joinClassSuccessCallBackData.DOCServerIP = GlobalConfig.DOCServerIP;
  1105 + joinClassSuccessCallBackData.DOCServerPort = GlobalConfig.DOCServerPort;
  1106 +
  1107 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  1108 + joinClassSuccessCallBackData.className = GlobalConfig.className;
  1109 + joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;
  1110 + joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;//
  1111 + joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
  1112 + joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
  1113 + joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
  1114 +
  1115 + joinClassSuccessCallBackData.msType = GlobalConfig.msType;
  1116 + joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;
  1117 + joinClassSuccessCallBackData.password = GlobalConfig.password;
  1118 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
  1119 + //GlobalConfig.passwordRequired 老师的默认是true
  1120 + //GlobalConfig.portal=_data.portal;
  1121 + joinClassSuccessCallBackData.role = GlobalConfig.role;
  1122 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  1123 + joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
  1124 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  1125 + joinClassSuccessCallBackData.userName = GlobalConfig.userName;
  1126 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  1127 + joinClassSuccessCallBackData.userType = GlobalConfig.userType;
  1128 +
  1129 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  1130 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  1131 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  1132 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  1133 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
  1134 + joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
  1135 +
  1136 + joinClassSuccessCallBackData.country = GlobalConfig.country;//国家
  1137 + joinClassSuccessCallBackData.city = GlobalConfig.city;//城市
  1138 + joinClassSuccessCallBackData.province = GlobalConfig.province;//服务商
  1139 + joinClassSuccessCallBackData.isp = GlobalConfig.isp;//服务商
  1140 +
  1141 + joinClassSuccessCallBackData.classTimestamp=GlobalConfig.classTimestamp;//课堂进行的累积时间
  1142 + joinClassSuccessCallBackData.recordPlaybackMaxTime=GlobalConfig.recordPlaybackMaxTime;//录制回放的总时间
  1143 +
  1144 + loger.log(joinClassSuccessCallBackData);
  1145 + //和加入课堂成功使用同样的消息处理
  1146 + this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);
  1147 + }
  1148 +
1032 } 1149 }
@@ -85,11 +85,13 @@ class EverSocket extends Emiter { @@ -85,11 +85,13 @@ class EverSocket extends Emiter {
85 loger.log('WebSocket,Timers销毁'); 85 loger.log('WebSocket,Timers销毁');
86 window.clearInterval(this.pingTimer); 86 window.clearInterval(this.pingTimer);
87 window.clearInterval(this.pongTimer); 87 window.clearInterval(this.pongTimer);
  88 + window.clearInterval(this.reConnectionTimeout);
  89 + this._setConnected(false);//先设置状态
  90 + this._enableEverSocket = false;
88 if(this.websocket==null){ 91 if(this.websocket==null){
89 loger.log('WebSocket,Timers已经销毁'); 92 loger.log('WebSocket,Timers已经销毁');
90 return; 93 return;
91 } 94 }
92 - this._setConnected(false);//先设置状态  
93 this.websocket.onopen = undefined; 95 this.websocket.onopen = undefined;
94 this.websocket.onclose = undefined; 96 this.websocket.onclose = undefined;
95 this.websocket.onerror = undefined; 97 this.websocket.onerror = undefined;
@@ -100,7 +102,7 @@ class EverSocket extends Emiter { @@ -100,7 +102,7 @@ class EverSocket extends Emiter {
100 loger.log('ignore errors'); 102 loger.log('ignore errors');
101 } 103 }
102 this.websocket = undefined; 104 this.websocket = undefined;
103 - this._enableEverSocket = false; 105 +
104 } 106 }
105 107
106 _onOpen() { 108 _onOpen() {
@@ -70,6 +70,7 @@ class GlobalConfig { @@ -70,6 +70,7 @@ class GlobalConfig {
70 classStatusInfo.classStartTime=this.classStartTime;//课堂点击开始时间 70 classStatusInfo.classStartTime=this.classStartTime;//课堂点击开始时间
71 classStatusInfo.classStopTime=this.classStopTime;//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳 71 classStatusInfo.classStopTime=this.classStopTime;//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
72 classStatusInfo.classTimestamp=this.classTimestamp;//相对于点开始课堂的时间戳 72 classStatusInfo.classTimestamp=this.classTimestamp;//相对于点开始课堂的时间戳
  73 + classStatusInfo.recordPlaybackMaxTime=this.recordPlaybackMaxTime;//相对于点开始课堂的时间戳
73 74
74 classStatusInfo.classBeginTime=this.classBeginTime;//课堂创建的时间,这个是Sass返回的 75 classStatusInfo.classBeginTime=this.classBeginTime;//课堂创建的时间,这个是Sass返回的
75 classStatusInfo.classEndTime=this.classEndTime;//课堂结束的时间,这个是Sass返回的 76 classStatusInfo.classEndTime=this.classEndTime;//课堂结束的时间,这个是Sass返回的
@@ -234,14 +235,14 @@ class GlobalConfig { @@ -234,14 +235,14 @@ class GlobalConfig {
234 } 235 }
235 236
236 GlobalConfig.statusCode_0={"code":0,message:"SDK 未初始化"}; 237 GlobalConfig.statusCode_0={"code":0,message:"SDK 未初始化"};
237 -GlobalConfig.statusCode_1={"code":1,message:"未加入会议"};  
238 -GlobalConfig.statusCode_2={"code":2,message:"已经加入会议"};  
239 -GlobalConfig.statusCode_3={"code":3,message:"已经离开会议"}; 238 +GlobalConfig.statusCode_1={"code":1,message:"未加入课堂"};
  239 +GlobalConfig.statusCode_2={"code":2,message:"已经加入课堂"};
  240 +GlobalConfig.statusCode_3={"code":3,message:"已经离开课堂"};
240 GlobalConfig.statusCode_4={"code":4,message:"未知状态"}; 241 GlobalConfig.statusCode_4={"code":4,message:"未知状态"};
241 242
242 GlobalConfig.md5=""; 243 GlobalConfig.md5="";
243 GlobalConfig.msType=1;//目前固定用这个 244 GlobalConfig.msType=1;//目前固定用这个
244 -GlobalConfig.mcuDelay=3000;//默认的延迟时间 245 +GlobalConfig.mcuDelay=60;//默认的延迟时间 flash中使用的是3000毫秒
245 GlobalConfig.docDelay=1600;//文档模块加入成功之后延迟发送送成功的消息给主模块 246 GlobalConfig.docDelay=1600;//文档模块加入成功之后延迟发送送成功的消息给主模块
246 GlobalConfig.portal="112.126.80.182:80";//Sass IP 247 GlobalConfig.portal="112.126.80.182:80";//Sass IP
247 248
@@ -272,7 +273,7 @@ GlobalConfig.hasCamera=false;//摄像头是否可用 @@ -272,7 +273,7 @@ GlobalConfig.hasCamera=false;//摄像头是否可用
272 GlobalConfig.hasMicrophone=false;//麦克风是否可用 273 GlobalConfig.hasMicrophone=false;//麦克风是否可用
273 274
274 GlobalConfig.deviceType=0; //设备类型 0:电脑 1:安卓 2:ios 275 GlobalConfig.deviceType=0; //设备类型 0:电脑 1:安卓 2:ios
275 -GlobalConfig.userIP="";//用户当前IP 276 +GlobalConfig.userIp="";//用户当前IP
276 GlobalConfig.userId=0; 277 GlobalConfig.userId=0;
277 GlobalConfig.userName=""; 278 GlobalConfig.userName="";
278 279
@@ -297,13 +298,14 @@ GlobalConfig.classBeginTime="";//课堂创建的时间,这个是Sass返回的 @@ -297,13 +298,14 @@ GlobalConfig.classBeginTime="";//课堂创建的时间,这个是Sass返回的
297 GlobalConfig.classEndTime="";//课堂结束的时间,这个是Sass返回的 298 GlobalConfig.classEndTime="";//课堂结束的时间,这个是Sass返回的
298 GlobalConfig.classTimestamp=0;//从课堂开始到现在的时 299 GlobalConfig.classTimestamp=0;//从课堂开始到现在的时
299 300
  301 +GlobalConfig.recordPlaybackMaxTime=0;//录制回放的总时间
300 GlobalConfig.recordStatus=false;//当前录制状态 302 GlobalConfig.recordStatus=false;//当前录制状态
301 GlobalConfig.recordTimestamp=0;//相对于首次开始录制的进行时间 303 GlobalConfig.recordTimestamp=0;//相对于首次开始录制的进行时间
302 GlobalConfig.recordFileName="";//录制的文件名,如 果为空就创建一个 304 GlobalConfig.recordFileName="";//录制的文件名,如 果为空就创建一个
303 GlobalConfig.recordDownloadUrl="";//下载地址 305 GlobalConfig.recordDownloadUrl="";//下载地址
304 GlobalConfig.recordReplaytickValues={}; // 滚动条关键点,用于快进快退 306 GlobalConfig.recordReplaytickValues={}; // 滚动条关键点,用于快进快退
305 307
306 -GlobalConfig.updateClassInfoDelay=30;//(秒),每隔30秒同步一次会议状态的并保存到Sass 308 +GlobalConfig.updateClassInfoDelay=30;//(秒),每隔30秒同步一次课堂状态的并保存到Sass
307 //GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get set 获取 309 //GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get set 获取
308 310
309 311
@@ -313,7 +315,7 @@ GlobalConfig.activeDocCurPage=1;//当前激活的文档的当前页 @@ -313,7 +315,7 @@ GlobalConfig.activeDocCurPage=1;//当前激活的文档的当前页
313 315
314 316
315 317
316 -GlobalConfig.classAllParam={};//Sass直接返回的所有会议信息(最全) 318 +GlobalConfig.classAllParam={};//Sass直接返回的所有课堂信息(最全)
317 GlobalConfig.classDetail={};//Sass直接返回的当前课堂基本信息 319 GlobalConfig.classDetail={};//Sass直接返回的当前课堂基本信息
318 320
319 GlobalConfig.docListPrepare=[]; // 已经提前上传的文档,进入课堂后需要自动加载 321 GlobalConfig.docListPrepare=[]; // 已经提前上传的文档,进入课堂后需要自动加载
@@ -323,7 +325,14 @@ GlobalConfig.mcuList=[];//录制服务器地址集合 @@ -323,7 +325,14 @@ GlobalConfig.mcuList=[];//录制服务器地址集合
323 GlobalConfig.msList=[];//ms服务器地址集合 325 GlobalConfig.msList=[];//ms服务器地址集合
324 GlobalConfig.musicList=[];//music服务器地址集合 326 GlobalConfig.musicList=[];//music服务器地址集合
325 GlobalConfig.musicListPrepare=[];//提提前上传的music集合 327 GlobalConfig.musicListPrepare=[];//提提前上传的music集合
326 -GlobalConfig.rsList=[]; 328 +GlobalConfig.rsList=[];//录制回放中视频点播地址
327 329
328 330
  331 +GlobalConfig.country ="";//国家
  332 +GlobalConfig.city ="";//城市
  333 +GlobalConfig.province = "";//服务商
  334 +GlobalConfig.isp ="";//服务商
  335 +
  336 +GlobalConfig.isRecordPlayBack=false;//是否是录制回放,默认是否
  337 +GlobalConfig.allowRecordMaxTime=14400;//(秒)允许录制的最长时间,默认是4小时
329 export default GlobalConfig; 338 export default GlobalConfig;
@@ -9,11 +9,11 @@ function MessageTypes() {} @@ -9,11 +9,11 @@ function MessageTypes() {}
9 MessageTypes.CLASS_INIT_SUCCESS="class_init_success";//'class.init.success';//初始化成功 9 MessageTypes.CLASS_INIT_SUCCESS="class_init_success";//'class.init.success';//初始化成功
10 //MessageTypes.CLASS_INIT_FAILED='class.init.failed';//初始化失败 10 //MessageTypes.CLASS_INIT_FAILED='class.init.failed';//初始化失败
11 11
12 -//加入会议相关事件定义 12 +//加入课堂相关事件定义
13 MessageTypes.CLASS_JOIN_MCU_SUCCESS ="class_join_mcu_success"// 'join.mcu.success'; 13 MessageTypes.CLASS_JOIN_MCU_SUCCESS ="class_join_mcu_success"// 'join.mcu.success';
14 //MessageTypes.CLASS_JOIN_FAILED = 'join.class.failed'; 14 //MessageTypes.CLASS_JOIN_FAILED = 'join.class.failed';
15 15
16 -//会议信息和操作事件定义 16 +//课堂信息和操作事件定义
17 //MessageTypes.CLASS_SHOW_DETAIL = 'class_detail.message'; 17 //MessageTypes.CLASS_SHOW_DETAIL = 'class_detail.message';
18 MessageTypes.CLASS_JOIN_SUCCESS ="class_join_success"// 'join.class.success'; 18 MessageTypes.CLASS_JOIN_SUCCESS ="class_join_success"// 'join.class.success';
19 MessageTypes.CLASS_UPDATE_ROSTER_NUM ="class_update_roster_num";// 'roster_num.message'; 19 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 @@ -21,9 +21,9 @@ MessageTypes.CLASS_INSERT_ROSTER ="class_insert_roster";// 'roster.insert.messag
21 MessageTypes.CLASS_DELETE_ROSTER ="class_delete_roster"// 'roster.delete.message'; 21 MessageTypes.CLASS_DELETE_ROSTER ="class_delete_roster"// 'roster.delete.message';
22 MessageTypes.CLASS_NONENTITY_ROSTER ="class_nonenetity_roster";// 'roster.nonentity.message'; 22 MessageTypes.CLASS_NONENTITY_ROSTER ="class_nonenetity_roster";// 'roster.nonentity.message';
23 23
24 -MessageTypes.CLASS_EXIT ="class_exit";// 'class.exit';//退出 关闭会议  
25 -MessageTypes.CLASS_UPTATE_STATUS ="class_update_status";// 'class.update.status';//更新会议状态信息  
26 -MessageTypes.CLASS_STATUS_INFO_CHANGE="class_status_info_change";// 'class.status.info.change';//会议状态信息发生改变,需要保存数据到sass和同步MCU 24 +MessageTypes.CLASS_EXIT ="class_exit";// 'class.exit';//退出 关闭课堂
  25 +MessageTypes.CLASS_UPTATE_STATUS ="class_update_status";// 'class.update.status';//更新课堂状态信息
  26 +MessageTypes.CLASS_STATUS_INFO_CHANGE="class_status_info_change";// 'class.status.info.change';//课堂状态信息发生改变,需要保存数据到sass和同步MCU
27 27
28 MessageTypes.CLASS_UPDATE_TIMER="class_update_timer";//'class.update.timer';//更新当前上课的时间 28 MessageTypes.CLASS_UPDATE_TIMER="class_update_timer";//'class.update.timer';//更新当前上课的时间
29 29
@@ -37,13 +37,13 @@ MessageTypes.CHAT_RECEIVE ="chat_receive_message";// 'chat.receive'; @@ -37,13 +37,13 @@ MessageTypes.CHAT_RECEIVE ="chat_receive_message";// 'chat.receive';
37 //视频模块事件定义 37 //视频模块事件定义
38 MessageTypes.VIDEO_PLAY ="video_play";// 'video.play';//播放视频 38 MessageTypes.VIDEO_PLAY ="video_play";// 'video.play';//播放视频
39 MessageTypes.VIDEO_STOP ="video_stop"; //'video.stop';//停止视频 39 MessageTypes.VIDEO_STOP ="video_stop"; //'video.stop';//停止视频
40 -//MessageTypes.VIDEO_UPDATE ="video.update";// 'video.update';//废弃,400、401取代 40 +MessageTypes.VIDEO_UPDATE ="video_update";// //这个监听事件不能删除,需要通知课堂模块,检查channel占用(内部使用)
41 MessageTypes.VIDEO_BROADCAST= "video_broadcast";//'video.broadcast'; 41 MessageTypes.VIDEO_BROADCAST= "video_broadcast";//'video.broadcast';
42 42
43 //音频模块事件定义 43 //音频模块事件定义
44 MessageTypes.AUDIO_PLAY ="audio_play";// 'audio.play';//播放 44 MessageTypes.AUDIO_PLAY ="audio_play";// 'audio.play';//播放
45 MessageTypes.AUDIO_STOP = "audio_stop";//'audio.stop';//停止 45 MessageTypes.AUDIO_STOP = "audio_stop";//'audio.stop';//停止
46 -//MessageTypes.AUDIO_UPDATE = "502";//'audio.update'; 46 +MessageTypes.AUDIO_UPDATE = "audio_update";//这个监听事件不能删除,需要通知课堂模块,检查channel占用(内部使用)
47 MessageTypes.AUDIO_BROADCAST= "audio_broadcast";//'audio.broadcast'; 47 MessageTypes.AUDIO_BROADCAST= "audio_broadcast";//'audio.broadcast';
48 48
49 49
@@ -57,8 +57,6 @@ MessageTypes.DOC_UPDATE ="document_update";// 'document.update';//更新文档( @@ -57,8 +57,6 @@ MessageTypes.DOC_UPDATE ="document_update";// 'document.update';//更新文档(
57 //MessageTypes.DOC_DELETE='document.delete';//删除文档 57 //MessageTypes.DOC_DELETE='document.delete';//删除文档
58 //MessageTypes.DOC_ANNOTATION = 'document.annotation';//笔记 58 //MessageTypes.DOC_ANNOTATION = 'document.annotation';//笔记
59 59
60 -  
61 -  
62 //白板笔记事件定义 60 //白板笔记事件定义
63 MessageTypes.WHITEBOARD_ANNOTATION_UPDATE ="whiteboard_annotation_update";// 'whiteboard.annotation.update'; 61 MessageTypes.WHITEBOARD_ANNOTATION_UPDATE ="whiteboard_annotation_update";// 'whiteboard.annotation.update';
64 //MessageTypes.WHITEBOARD_ANNOTAION_INSERT = 'whiteboard.annotation.insert'; 62 //MessageTypes.WHITEBOARD_ANNOTAION_INSERT = 'whiteboard.annotation.insert';
@@ -66,6 +64,9 @@ MessageTypes.WHITEBOARD_ANNOTATION_UPDATE ="whiteboard_annotation_update";// 'wh @@ -66,6 +64,9 @@ MessageTypes.WHITEBOARD_ANNOTATION_UPDATE ="whiteboard_annotation_update";// 'wh
66 //MessageTypes.WHITEBOARD_ANNOTATION_CLEAR = 'whiteboard.annotation.clear'; 64 //MessageTypes.WHITEBOARD_ANNOTATION_CLEAR = 'whiteboard.annotation.clear';
67 65
68 66
  67 +//录制回放
  68 +MessageTypes.RECORD_PLAYBACK_UPDATE ="record_playback_update";//录制回放更新信息
  69 +
69 //错误事件定义 70 //错误事件定义
70 MessageTypes.MCU_ERROR ="mcu_error";//"mcuError";//MCU错误(内部使用) 71 MessageTypes.MCU_ERROR ="mcu_error";//"mcuError";//MCU错误(内部使用)
71 MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使用) 72 MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使用)
@@ -73,7 +74,7 @@ MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使 @@ -73,7 +74,7 @@ MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使
73 74
74 //---------------错误消息 ErrorCode 定义------------------------------------------------- 75 //---------------错误消息 ErrorCode 定义-------------------------------------------------
75 76
76 -//会议初始化失败的几种情况 77 +//课堂初始化失败的几种情况
77 MessageTypes.ERR_CLASS_INIT_PARAM=100;//初始化参数错误 78 MessageTypes.ERR_CLASS_INIT_PARAM=100;//初始化参数错误
78 MessageTypes.ERR_CLASS_INIT_NETWORK=101;//初始化网络错误 79 MessageTypes.ERR_CLASS_INIT_NETWORK=101;//初始化网络错误
79 MessageTypes.ERR_CLASS_INIT_PROTOCOL=102;//初始化协议错误 80 MessageTypes.ERR_CLASS_INIT_PROTOCOL=102;//初始化协议错误
@@ -83,22 +84,22 @@ MessageTypes.ERR_CLASS_INIT_FAILED_2=105;//初始化验证失败,无效的课堂 @@ -83,22 +84,22 @@ MessageTypes.ERR_CLASS_INIT_FAILED_2=105;//初始化验证失败,无效的课堂
83 MessageTypes.ERR_CLASS_INIT_FAILED_3=106;//初始化验证失败,没有对应的站点 84 MessageTypes.ERR_CLASS_INIT_FAILED_3=106;//初始化验证失败,没有对应的站点
84 MessageTypes.ERR_CLASS_INIT_FAILED_4=107;//初始化验证失败,站点已过期 85 MessageTypes.ERR_CLASS_INIT_FAILED_4=107;//初始化验证失败,站点已过期
85 86
86 -//加入会议失败的几种情况  
87 -MessageTypes.ERR_CLASS_JOIN_NETWORK=200;//加入会议网络错误  
88 -MessageTypes.ERR_CLASS_JOIN_PROTOCOL=201;//加入会议化协议错误  
89 -MessageTypes.ERR_CLASS_JOIN_FAILED=202;//加入会议化异常错误  
90 -MessageTypes.ERR_CLASS_JOIN_PARAM=203;//加入会议参数错误 87 +//加入课堂失败的几种情况
  88 +MessageTypes.ERR_CLASS_JOIN_NETWORK=200;//加入课堂网络错误
  89 +MessageTypes.ERR_CLASS_JOIN_PROTOCOL=201;//加入课堂化协议错误
  90 +MessageTypes.ERR_CLASS_JOIN_FAILED=202;//加入课堂化异常错误
  91 +MessageTypes.ERR_CLASS_JOIN_PARAM=203;//加入课堂参数错误
91 MessageTypes.ERR_CLASS_JOIN_FULL=204;//人数已满 92 MessageTypes.ERR_CLASS_JOIN_FULL=204;//人数已满
92 MessageTypes.ERR_CLASS_MD5_WRONG=205;//MD5验证失败 93 MessageTypes.ERR_CLASS_MD5_WRONG=205;//MD5验证失败
93 MessageTypes.ERR_CLASS_PASSWORD_WRONG=206;//密码错误 94 MessageTypes.ERR_CLASS_PASSWORD_WRONG=206;//密码错误
94 MessageTypes.ERR_CLASS_JOIN_CONFILICT=207;//已经在其它地方登陆 95 MessageTypes.ERR_CLASS_JOIN_CONFILICT=207;//已经在其它地方登陆
95 - 96 +MessageTypes.ERR_CLASS_KICK_OUT=208;//有相同身份的人员加入课堂,自己被踢出;
96 97
97 MessageTypes.ERR_GET_CLASS_DETAIL=300;//获取classDetail失败 98 MessageTypes.ERR_GET_CLASS_DETAIL=300;//获取classDetail失败
98 MessageTypes.ERR_GET_CLASS_PARAML=301;//获取ClassParam失败 99 MessageTypes.ERR_GET_CLASS_PARAML=301;//获取ClassParam失败
99 100
100 //APE 101 //APE
101 -MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN=500;//APE在sdk为初始化或未加入会议之前调用发送数据接口 102 +MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN=500;//APE在sdk为初始化或未加入课堂之前调用发送数据接口
102 MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG=501;//APE在接口调用时参数错误 103 MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG=501;//APE在接口调用时参数错误
103 104
104 //DOC 105 //DOC
@@ -110,10 +111,15 @@ MessageTypes.ERR_SDK_FAILED=700;// sdk还没初始化 @@ -110,10 +111,15 @@ MessageTypes.ERR_SDK_FAILED=700;// sdk还没初始化
110 MessageTypes.ERR_INTERFACE_NONE=701;//调用的接口不存在 111 MessageTypes.ERR_INTERFACE_NONE=701;//调用的接口不存在
111 MessageTypes.ERR_INTERFACE_PARAMS_ERROR=702;//调用的接口,传递的参数不正确 112 MessageTypes.ERR_INTERFACE_PARAMS_ERROR=702;//调用的接口,传递的参数不正确
112 113
  114 +
  115 +MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED=910;//初始化录制回放失败
  116 +MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED=911;//获取录制回放数据失败
  117 +
  118 +
113 MessageTypes.ERR_NETWORK=10000;//网络错误 119 MessageTypes.ERR_NETWORK=10000;//网络错误
114 MessageTypes.ERR_UNKNOWN=10001;//未知错误 120 MessageTypes.ERR_UNKNOWN=10001;//未知错误
115 121
116 -MessageTypes.ERR_SOCKET_DISCONNECT=20000;//MCU断开连接,已经离开会议 122 +MessageTypes.ERR_SOCKET_DISCONNECT=20000;//MCU断开连接,已经离开课堂
117 123
118 //---------------错误消息 Error Reson 定义------------------------------------------------- 124 //---------------错误消息 Error Reson 定义-------------------------------------------------
119 MessageTypes.ErrorReson={}; 125 MessageTypes.ErrorReson={};
@@ -128,22 +134,23 @@ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_3]="初始化验证 @@ -128,22 +134,23 @@ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_3]="初始化验证
128 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_4]="初始化验证失败,站点已过期"; 134 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_4]="初始化验证失败,站点已过期";
129 135
130 136
131 -//加入会议失败的几种情况  
132 -MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_NETWORK]="加入会议网络错误";  
133 -MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PROTOCOL]="加入会议化协议错误";  
134 -MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FAILED]="加入会议化异常错误";  
135 -MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PARAM]="加入会议参数错误"; 137 +//加入课堂失败的几种情况
  138 +MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_NETWORK]="加入课堂网络错误";
  139 +MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PROTOCOL]="加入课堂化协议错误";
  140 +MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FAILED]="加入课堂化异常错误";
  141 +MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PARAM]="加入课堂参数错误";
136 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FULL]="人数已满"; 142 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FULL]="人数已满";
137 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_MD5_WRONG]="MD5验证失败"; 143 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_MD5_WRONG]="MD5验证失败";
138 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_PASSWORD_WRONG]="密码错误"; 144 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_PASSWORD_WRONG]="密码错误";
139 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_CONFILICT]="已经在其它地方登陆"; 145 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_CONFILICT]="已经在其它地方登陆";
  146 +MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_KICK_OUT]="有相同身份的人员加入课堂,自己被踢出课堂";
140 147
141 148
142 MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_DETAIL]="获取classDetail失败"; 149 MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_DETAIL]="获取classDetail失败";
143 MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_PARAML]="获取ClassParam失败"; 150 MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_PARAML]="获取ClassParam失败";
144 151
145 //APE 152 //APE
146 -MessageTypes.ErrorReson[MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN]="APE在sdk为初始化或未加入会议之前调用发送数据接口"; 153 +MessageTypes.ErrorReson[MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN]="APE在sdk为初始化或未加入课堂之前调用发送数据接口";
147 MessageTypes.ErrorReson[MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG]="APE在接口调用时参数错误"; 154 MessageTypes.ErrorReson[MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG]="APE在接口调用时参数错误";
148 155
149 //DOC 156 //DOC
@@ -154,10 +161,16 @@ MessageTypes.ErrorReson[MessageTypes.ERR_SDK_FAILED]="sdk还没初始化"; @@ -154,10 +161,16 @@ MessageTypes.ErrorReson[MessageTypes.ERR_SDK_FAILED]="sdk还没初始化";
154 MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_NONE]="调用的接口不存在"; 161 MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_NONE]="调用的接口不存在";
155 MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_PARAMS_ERROR]="调用的接口,传递的参数不正确"; 162 MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_PARAMS_ERROR]="调用的接口,传递的参数不正确";
156 163
  164 +
  165 +MessageTypes.ErrorReson[MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED]="初始化录制回放失败";
  166 +MessageTypes.ErrorReson[MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED]="获取录制回放数据失败";
  167 +
  168 +
  169 +
157 MessageTypes.ErrorReson[MessageTypes.ERR_NETWORK]="网络错误"; 170 MessageTypes.ErrorReson[MessageTypes.ERR_NETWORK]="网络错误";
158 MessageTypes.ErrorReson[MessageTypes.ERR_UNKNOWN]="未知错误"; 171 MessageTypes.ErrorReson[MessageTypes.ERR_UNKNOWN]="未知错误";
159 172
160 -MessageTypes.ErrorReson[MessageTypes.ERR_SOCKET_DISCONNECT]="MCU断开连接,已经离开会议"; 173 +MessageTypes.ErrorReson[MessageTypes.ERR_SOCKET_DISCONNECT]="MCU断开连接,已经离开课堂";
161 174
162 175
163 176
  1 +import ByteBuffer from 'libs/bytebuffer.min';
  2 +import Emiter from 'Emiter';
  3 +import MessageTypes from 'MessageTypes';
  4 +import Loger from 'Loger';
  5 +
  6 +import pdu from 'pdus/index';
  7 +import PduType from 'pdus/PduType';
  8 +import PduConsts from 'pdus/PduConsts';
  9 +import ApeConsts from 'apes/ApeConsts';
  10 +import ArrayBufferUtil from 'libs/ArrayBufferUtil';
  11 +import Base64 from 'base64-js';
  12 +import GlobalConfig from 'GlobalConfig';
  13 +import EngineUtils from 'EngineUtils';
  14 +import TimerCounter from "TimerCounter";
  15 +
  16 +
  17 +let parseBuffer;
  18 +// 日志对象
  19 +const loger = Loger.getLoger('RecordPlayBackParse');
  20 +const Default = 0;//未开始
  21 +const PLAY = 1;//播放中
  22 +const PAUSE = 2;//暂停
  23 +const SEEK = 3;//seek
  24 +const STOP = 4;//停止
  25 +
  26 +class RecordPlayBackParse extends Emiter {
  27 + constructor() {
  28 + super();
  29 + loger.log("RecordPlayBackParse");
  30 + parseBuffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
  31 + parseBuffer.clear();
  32 + //console.log(parseBuffer);
  33 + this._recordPlaybackTimestamp = 0;//回放的时间
  34 + this._recordPlaybackMaxTime = 0;//录制回放的总时间
  35 + this._isReady = false;//录制回放是否已经准备完成
  36 + this._apes = {};
  37 + //this._messages = {};
  38 +
  39 + this._conferApeMssages = {};//会议数据
  40 + this._chatApeMssages = {};//聊天数据
  41 + this._videoApeMssages = {};//视频数据
  42 + this._audioApeMssages = {};//音频数据
  43 + this._docApeMssages = {};//文档数据
  44 + this._whiteApeMssages = {};//白板数据
  45 +
  46 + this._timerCounter = new TimerCounter();//计时器
  47 + this._timerCounter.addTimerCallBack(this._timerCounterUptate.bind(this), 1);
  48 + }
  49 +
  50 + //method--------------------内部---------------------------------------------
  51 + // 注册Ape
  52 + registerApe(ape) {
  53 + this._apes[ape._session_id] = ape;
  54 + }
  55 +
  56 + initReplay() {
  57 + this._stopTimerCounter();
  58 + this._recordPlaybackTimestamp = 0;//回放的时间
  59 + this._recordPlaybackMaxTime = 0;//录制回放的总时间
  60 + this._isReady = false;//录制回放是否已经准备完成
  61 +
  62 + this._conferApeMssages = {};//会议数据
  63 + this._chatApeMssages = {};//聊天数据
  64 + this._videoApeMssages = {};//视频数据
  65 + this._audioApeMssages = {};//音频数据
  66 + this._docApeMssages = {};//文档数据
  67 + this._whiteApeMssages = {};//白板数据
  68 + }
  69 +
  70 + //发送数据个各个APE模块处理,data是数据,seekTime是当前数据需要seek的时间长度(针对音视频的seek)
  71 + _everSocketMsgReceivedHandler(data, seekTime) {
  72 + let pduMsg = pdu.decode_pdu(data);
  73 + let pduType = pduMsg.get("type");
  74 + let pduData = pduMsg.get("data");
  75 + //*************非常重要******************
  76 + //客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端,
  77 + //所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的
  78 + if (pduType == PduType.RCPDU_UNIFORM_SEND_DATA_REQUEST) {
  79 + pduMsg.type = PduType.RCPDU_SEND_DATA_REQUEST;
  80 + pduType = PduType.RCPDU_SEND_DATA_REQUEST;
  81 + }
  82 + loger.log('_everSocketMsgReceivedHandler->pduType', pduType, "seekTime->", seekTime);
  83 + switch (pduType) {
  84 + case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
  85 + //加入课堂请求返回数据处理
  86 + let joinConfPdu = pdu['RCConferenceJoinResponsePdu'].decode(pduData);
  87 + let pduResultCode = joinConfPdu.result;
  88 + loger.warn('RCPDU_CONNECT_PROVIDER_RESPONSE ->pduResultCode:' + pduResultCode);
  89 + switch (pduResultCode) {
  90 + case PduConsts.RET_SUCCESS:
  91 + //加入成功
  92 + //this._updateMCUConfInfoDescription(joinConfPdu.classDescription);
  93 + this._emit(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this.classInfo);
  94 + break;
  95 + case PduConsts.RET_FULL_CAPACITY:
  96 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FULL);
  97 + break;
  98 + default:
  99 + loger.warn('JoinConfPdu-未知类型-等待处理.', pduResultCode);
  100 + break
  101 + }
  102 + break;
  103 + case PduType.RCPDU_SEND_DATA_REQUEST:
  104 + //先判断当前消息属于哪个APE 根据 sessionId来判断
  105 + let ape = this._apes[pduMsg.sessionId];
  106 + let sessionLabel = ApeConsts(pduMsg.sessionId);
  107 + //对方发送消息
  108 + if (ape) {
  109 + let subTypeLabel = pdu.id2type(pduMsg.subType);
  110 + //loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType);
  111 + //ape广播事件,只要ape中监听就能收到
  112 + ape._emit(pduMsg.subType, pduMsg.data, seekTime);//seekTime是音视频模块seek的时间长度
  113 + } else {
  114 + loger.warn(sessionLabel + '尚未注册');
  115 + }
  116 + break;
  117 + default:
  118 + loger.warn('PDU-未知类型-等待处理.', pduType);
  119 + }
  120 + }
  121 +
  122 + //解析和储存,录制回放EverSocket底层消息处理 data-数据;timestamp-数据对应的时间戳
  123 + _parseSaveSocketMsgReceivedHandler(data, timestamp) {
  124 + let pduMsg = pdu.decode_pdu(data);
  125 + let pduType = pduMsg.get("type");
  126 + let pduData = pduMsg.get("data");
  127 + //*************非常重要******************
  128 + //客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端,
  129 + //所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的
  130 + if (pduType == PduType.RCPDU_UNIFORM_SEND_DATA_REQUEST) {
  131 + pduMsg.type = PduType.RCPDU_SEND_DATA_REQUEST;
  132 + pduType = PduType.RCPDU_SEND_DATA_REQUEST;
  133 + }
  134 + loger.log('pduType', pduType);
  135 + switch (pduType) {
  136 + case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
  137 + //加入课堂请求返回数据处理
  138 + let joinConfPdu = pdu['RCConferenceJoinResponsePdu'].decode(pduData);
  139 + let pduResultCode = joinConfPdu.result;
  140 + loger.warn('RCPDU_CONNECT_PROVIDER_RESPONSE ->pduResultCode:' + pduResultCode);
  141 + switch (pduResultCode) {
  142 + case PduConsts.RET_SUCCESS:
  143 + //加入成功
  144 + //this._updateMCUConfInfoDescription(joinConfPdu.classDescription);
  145 + this._emit(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this.classInfo);
  146 + break;
  147 + case PduConsts.RET_FULL_CAPACITY:
  148 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FULL);
  149 + break;
  150 + default:
  151 + loger.warn('JoinConfPdu-未知类型-等待处理.', pduResultCode);
  152 + break
  153 + }
  154 + break;
  155 + case PduType.RCPDU_SEND_DATA_REQUEST:
  156 + //先判断当前消息属于哪个APE 根据 sessionId来判断
  157 + let ape = this._apes[pduMsg.sessionId];
  158 + let sessionLabel = ApeConsts(pduMsg.sessionId);
  159 + //只做解析存储,不对外发送
  160 + loger.log('解析数据-timestamp->', timestamp, 'sessionId->', pduMsg.sessionId, 'sessionLabel->', sessionLabel);
  161 + switch (pduMsg.sessionId) {
  162 + case ApeConsts.CONFERENCE_SESSION_ID:
  163 + this.saveParseData(data, timestamp, this._conferApeMssages);
  164 + break;
  165 + case ApeConsts.CHAT_SESSION_ID:
  166 + this.saveParseData(data, timestamp, this._chatApeMssages);
  167 + break;
  168 + case ApeConsts.DOCSHARING_SESSION_ID:
  169 + this.saveParseData(data, timestamp, this._docApeMssages);
  170 + break;
  171 + case ApeConsts.WHITEBOARD_SESSION_ID:
  172 + this.saveParseData(data, timestamp, this._whiteApeMssages);
  173 + break;
  174 + case ApeConsts.VIDEO_SESSION_ID:
  175 + this.saveParseData(data, timestamp, this._videoApeMssages);
  176 + break;
  177 + case ApeConsts.AUDIO_SESSION_ID:
  178 + this.saveParseData(data, timestamp, this._audioApeMssages);
  179 + break;
  180 + default:
  181 + break;
  182 + }
  183 +
  184 + break;
  185 + default:
  186 + loger.warn('PDU-未知类型-等待处理.', pduType);
  187 + }
  188 + }
  189 +
  190 + //保存数据
  191 + saveParseData(data, timestamp, apeMessages) {
  192 + let messageItem = apeMessages[timestamp];
  193 + if (!messageItem) {
  194 + apeMessages[timestamp] = [];//数组存数据,因为有1秒内收到多个消息的情况,timestamp是按秒记录的
  195 + messageItem = apeMessages[timestamp];
  196 + }
  197 + messageItem.push({"timestamp": timestamp, "byteData": data});
  198 +
  199 + }
  200 +
  201 + //开启计时器
  202 + _startTimerCounter() {
  203 + if (this._timerCounter) {
  204 + this._timerCounter.startTimer();
  205 + }
  206 + }
  207 +
  208 + //停止计时器
  209 + _stopTimerCounter() {
  210 + if (this._timerCounter) {
  211 + this._timerCounter.stopTimer();
  212 + }
  213 +
  214 + }
  215 +
  216 + _timerCounterUptate() {
  217 + this._recordPlaybackTimestamp = this._recordPlaybackTimestamp + 1;//计时
  218 + if (this._recordPlaybackTimestamp >= this._recordPlaybackMaxTime) {
  219 + this._stopTimerCounter();
  220 + loger.log("录制回放结束...当前时间->", this._recordPlaybackTimestamp, " 总时间->", this._recordPlaybackMaxTime);
  221 + this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": STOP});
  222 + return;
  223 + }
  224 +
  225 + loger.log("录制回放中...", this._recordPlaybackTimestamp);
  226 + this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": this._recordPlaybackTimestamp});
  227 +
  228 + //各个APE模块根据时间查找消息数据
  229 + this._searchMessageFromTime(this._recordPlaybackTimestamp, this._conferApeMssages);
  230 + this._searchMessageFromTime(this._recordPlaybackTimestamp, this._chatApeMssages);
  231 + this._searchMessageFromTime(this._recordPlaybackTimestamp, this._docApeMssages);
  232 + this._searchMessageFromTime(this._recordPlaybackTimestamp, this._whiteApeMssages);
  233 + this._searchMessageFromTime(this._recordPlaybackTimestamp, this._videoApeMssages);
  234 + this._searchMessageFromTime(this._recordPlaybackTimestamp, this._audioApeMssages);
  235 + }
  236 +
  237 + //加载录制文件
  238 + readyRecordPlay() {
  239 + this.initReplay();
  240 + loger.log("读取回放数据");
  241 + //let url = `http://123.56.73.119:80/h5dev/20170306/1357644520_20170306.rec`;
  242 + let url = `http://${ GlobalConfig.RecordServerIP}:${ GlobalConfig.RecordServerPort}/${GlobalConfig.recordFileName}`;
  243 + loger.log(url);
  244 + fetch(url, {
  245 + timeout: 90000 //加载文件超时时间1分30秒
  246 + })
  247 + .then(ret => {
  248 + if (ret.ok) {
  249 + return ret.arrayBuffer();
  250 + } else {
  251 + loger.error(`读取回放数据-网络异常.状态码:${ret.status}`);
  252 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
  253 + throw '';
  254 + }
  255 + })
  256 + .then(ret => {
  257 + if (ret) {
  258 + loger.log('读取回放数据-完成');
  259 + this._loadRecordDataSuccess(ret);
  260 + } else {
  261 + loger.warn('读取回放数据-失败.');
  262 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
  263 + }
  264 + })
  265 + .catch(err => {
  266 + loger.error(`读取回放数据.状态码:${err}`);
  267 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
  268 + });
  269 + }
  270 +
  271 + _loadRecordDataSuccess(arrayBuffer) {
  272 + loger.log("获取录制回放数据的长度", arrayBuffer.byteLength);
  273 + if (parseBuffer) {
  274 + parseBuffer.clear();
  275 + parseBuffer.append(arrayBuffer);
  276 + //解析数据
  277 + this.parseArrayBuf();
  278 + }
  279 + }
  280 +
  281 + //解析数据
  282 + parseArrayBuf() {
  283 + //this._messages = {};
  284 + let byteLength = parseBuffer.offset;
  285 + parseBuffer.byteOffset = 0;
  286 + var position = 0;
  287 + while (position < byteLength) {
  288 + let timestamp = parseBuffer.readUInt32(position);
  289 + position += 4;//4字节
  290 + let byteLen = parseBuffer.readUInt32(position);
  291 + position += 4;//4字节
  292 + let byteData = parseBuffer.buffer.slice(position, (position + byteLen));
  293 + position += byteLen;
  294 +
  295 + this._parseSaveSocketMsgReceivedHandler(byteData, timestamp);
  296 + //记录最后一个数据的时间戳作为整个录制回放的总时间戳
  297 + this._recordPlaybackMaxTime = timestamp;
  298 + }
  299 + this._recordPlaybackTimestamp = 0;
  300 + this._isReady = true;
  301 + this._stopTimerCounter();
  302 +
  303 + GlobalConfig.recordPlaybackMaxTime = this._recordPlaybackMaxTime;
  304 + loger.log("录制回放数据解析完成,录制回放的总时间长为->", this._recordPlaybackMaxTime);
  305 + //console.log("_messages", this._messages);
  306 + loger.log("_conferApeMssages", this._conferApeMssages);
  307 + loger.log("_chatApeMssages", this._chatApeMssages);
  308 + loger.log("_docApeMssages", this._docApeMssages);
  309 + loger.log("_whiteApeMssages", this._whiteApeMssages);
  310 + loger.log("_videoApeMssages", this._videoApeMssages);
  311 + loger.log("_audioApeMssages", this._audioApeMssages);
  312 +
  313 + this._emit(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, {"recordPlaybackMaxTime": this._recordPlaybackMaxTime});
  314 + }
  315 +
  316 + //根据时间查找数据
  317 + _searchMessageFromTime(_timestamp, _apeMessages) {
  318 + let msgDataArr = _apeMessages[_timestamp];
  319 + if (!msgDataArr) {
  320 + //没有数据,需要查找当前时间点属于哪一个时间戳关键帧
  321 + } else {
  322 + //把时间点对应的数据发送,同一秒内有存在多个数据的情况
  323 + for (let i = 0; i < msgDataArr.length; i++) {
  324 + this._everSocketMsgReceivedHandler(msgDataArr[i].byteData, 0);
  325 + }
  326 + }
  327 + }
  328 +
  329 + /*_searchMessageFromTime(_timestamp,_apeMessages){
  330 + let msgDataArr=this._messages[_timestamp];
  331 + if(!msgDataArr){
  332 + //没有数据,需要查找当前时间点属于哪一个时间戳关键帧
  333 + }else {
  334 + //把时间点对应的数据发送,同一秒内有存在多个数据的情况
  335 + for(let i=0;i<msgDataArr.length;i++){
  336 + this._everSocketMsgReceivedHandler(msgDataArr[i].byteData);
  337 + }
  338 + }
  339 + }*/
  340 +
  341 + //method------------外部接口-------------------------------------
  342 +
  343 + //开始播放
  344 + startRecordPlayback(_param) {
  345 + if (!this._isReady) {
  346 + return {"code": ApeConsts.RETURN_FAILED, "data": "录制回放还未准备完成"};
  347 + }
  348 + this._startTimerCounter();
  349 + this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": PLAY});
  350 + }
  351 +
  352 + //停止播放
  353 + stopRecordPlayback(_param) {
  354 + this._recordPlaybackTimestamp = 0;
  355 + this._stopTimerCounter();
  356 + this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": STOP});
  357 + }
  358 +
  359 + //暂停播放
  360 + pauseRecordPlayback(_param) {
  361 + this._stopTimerCounter();
  362 + this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": PAUSE});
  363 + }
  364 +
  365 + //跳转到指定时间点播放
  366 + seekRecordPlayback(_param) {
  367 + if (!this._isReady) {
  368 + return {"code": ApeConsts.RETURN_FAILED, "data": "录制回放还未准备完成"};
  369 + }
  370 + if (!_param || !_param.time) {
  371 + return {"code": ApeConsts.RETURN_FAILED, "data": "参数不正确"};
  372 + }
  373 + //先暂停,更改进行的时间
  374 + this._stopTimerCounter()
  375 + this._recordPlaybackTimestamp = _param.time || 0;
  376 +
  377 + //各个ape模块查找关键帧数据
  378 + this._searchKeyfram();
  379 + }
  380 +
  381 + _searchKeyfram() {
  382 + //查找关键帧,找到关键帧后再继续播放
  383 + this._searchApeMessageKeyfram(this._conferApeMssages, ApeConsts.CONFERENCE_SESSION_ID);
  384 + this._searchApeMessageKeyfram(this._docApeMssages, ApeConsts.DOCSHARING_SESSION_ID);
  385 + this._searchApeMessageKeyfram(this._whiteApeMssages, ApeConsts.WHITEBOARD_SESSION_ID);
  386 + this._searchApeMessageKeyfram(this._videoApeMssages, ApeConsts.VIDEO_SESSION_ID);
  387 + this._searchApeMessageKeyfram(this._audioApeMssages, ApeConsts.AUDIO_SESSION_ID);
  388 +
  389 + //聊天模块的比较特殊,消息是累计的
  390 + this._searchChatApeMessageKeyfram(this._chatApeMssages, ApeConsts.CHAT_SESSION_ID);
  391 +
  392 +
  393 + //各个ape模块无论有没有找到关键帧数据,都继续播放
  394 + this._startTimerCounter();
  395 + }
  396 +
  397 + //查找ape关键帧数据
  398 + _searchApeMessageKeyfram(_apeMessages, _apeId) {
  399 + let messageItem;
  400 + let keyFrameSeekTime = 0;
  401 + for (let i = this._recordPlaybackTimestamp; i > 0; i--) {
  402 + messageItem = _apeMessages[i];
  403 + if (messageItem) {
  404 + keyFrameSeekTime = (this._recordPlaybackTimestamp - i)
  405 + loger.log("SEEK->APE", ApeConsts(_apeId), this._recordPlaybackTimestamp, "查找到相连的timestamp->", i, '需要seek->', keyFrameSeekTime, "秒");
  406 + //把时间点对应的数据发送,同一秒内有存在多个数据的情况
  407 + for (let k = 0; k < messageItem.length; k++) {
  408 + this._everSocketMsgReceivedHandler(messageItem[k].byteData, keyFrameSeekTime);
  409 + }
  410 + if (_apeId == ApeConsts.AUDIO_SESSION_ID || _apeId == ApeConsts.VIDEO_SESSION_ID) {
  411 + this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {
  412 + "status": SEEK,
  413 + "keyFrameSeekTime": keyFrameSeekTime
  414 + });
  415 + }
  416 + return;
  417 + }
  418 + }
  419 + loger.log("SEEK->APE", ApeConsts(_apeId), this._recordPlaybackTimestamp, "没有查找到相连的数据");
  420 + }
  421 +
  422 + //查找聊天模块ape关键帧数据,聊天模块比较特殊,消息是累积的,当前时间戳之前的都需要显示
  423 + _searchChatApeMessageKeyfram(_apeMessages) {
  424 + let messageItem;
  425 + let keyFrameSeek = 0;
  426 + for (let i = this._recordPlaybackTimestamp; i > 0; i--) {
  427 + messageItem = _apeMessages[i];
  428 + if (messageItem) {
  429 + //把时间点对应的数据发送,同一秒内有存在多个数据的情况
  430 + for (let i = 0; i < messageItem.length; i++) {
  431 + this._everSocketMsgReceivedHandler(messageItem[i].byteData, 0);
  432 + }
  433 + }
  434 + }
  435 + }
  436 +
  437 +}
  438 +
  439 +RecordPlayBackParse.prototype.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS = RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS = 'class_join_recordPlayback_success';//加入录制回放成功
  440 +
  441 +export default new RecordPlayBackParse;
  442 +
@@ -4,6 +4,9 @@ import MessageTypes from 'MessageTypes'; @@ -4,6 +4,9 @@ import MessageTypes from 'MessageTypes';
4 import GlobalConfig from 'GlobalConfig'; 4 import GlobalConfig from 'GlobalConfig';
5 import MD5 from "md5"; 5 import MD5 from "md5";
6 import ApeConsts from 'apes/ApeConsts'; 6 import ApeConsts from 'apes/ApeConsts';
  7 +import iphunter from 'iphunter';
  8 +
  9 +import fetchJsonp from 'fetch-jsonp';
7 10
8 // 日志对象 11 // 日志对象
9 const loger = Loger.getLoger('Sass'); 12 const loger = Loger.getLoger('Sass');
@@ -37,8 +40,8 @@ class Sass extends Emiter { @@ -37,8 +40,8 @@ class Sass extends Emiter {
37 */ 40 */
38 let url = `http://${_initInfo.portal}/3m/api/meeting/joinParams.do?meetingNumber=${_initInfo.classId}&userID=${_initInfo.userId}`; 41 let url = `http://${_initInfo.portal}/3m/api/meeting/joinParams.do?meetingNumber=${_initInfo.classId}&userID=${_initInfo.userId}`;
39 loger.log('1.初始化init获取课堂校验信息.'); 42 loger.log('1.初始化init获取课堂校验信息.');
40 - console.log(url);  
41 - console.log(_initInfo); 43 + loger.log(url);
  44 + loger.log(_initInfo);
42 fetch(url, { 45 fetch(url, {
43 timeout: 5000 46 timeout: 5000
44 }) 47 })
@@ -85,7 +88,7 @@ class Sass extends Emiter { @@ -85,7 +88,7 @@ class Sass extends Emiter {
85 // Sass校验开始-->密码校验(如果需要密码)--->MD5校验---------------------------------------------------- 88 // Sass校验开始-->密码校验(如果需要密码)--->MD5校验----------------------------------------------------
86 passwordAndMd5Checking(_param) { 89 passwordAndMd5Checking(_param) {
87 loger.log('2.开始Sass校验'); 90 loger.log('2.开始Sass校验');
88 - console.log(_param); 91 + loger.log(_param);
89 confInfo = _param; 92 confInfo = _param;
90 // 密码校验 93 // 密码校验
91 if (confInfo.passwordRequired === 'true' || confInfo.passwordRequired === true) { 94 if (confInfo.passwordRequired === 'true' || confInfo.passwordRequired === true) {
@@ -114,7 +117,7 @@ class Sass extends Emiter { @@ -114,7 +117,7 @@ class Sass extends Emiter {
114 } 117 }
115 118
116 let url = `http://${confInfo.portal}/3m/api/meeting/signIn.do?siteId=${confInfo.siteId}&classId=${confInfo.classId}&isTeacher=${isTeacher}&password=${confInfo.password}`; 119 let url = `http://${confInfo.portal}/3m/api/meeting/signIn.do?siteId=${confInfo.siteId}&classId=${confInfo.classId}&isTeacher=${isTeacher}&password=${confInfo.password}`;
117 - loger.log('3.会议密码校验', url); 120 + loger.log('3.课堂密码校验', url);
118 fetch(url, { 121 fetch(url, {
119 timeout: 5000 122 timeout: 5000
120 }) 123 })
@@ -122,7 +125,7 @@ class Sass extends Emiter { @@ -122,7 +125,7 @@ class Sass extends Emiter {
122 if (ret.status === 200) { 125 if (ret.status === 200) {
123 return ret.text(); 126 return ret.text();
124 } else { 127 } else {
125 - loger.error(`会议密码校验-网络异常.状态码:${ret.status}`); 128 + loger.error(`课堂密码校验-网络异常.状态码:${ret.status}`);
126 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_NETWORK); 129 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_NETWORK);
127 throw ''; 130 throw '';
128 } 131 }
@@ -130,20 +133,20 @@ class Sass extends Emiter { @@ -130,20 +133,20 @@ class Sass extends Emiter {
130 .then(ret => { 133 .then(ret => {
131 let rectObj = JSON.parse(ret); 134 let rectObj = JSON.parse(ret);
132 if (rectObj.flag === 'false' || rectObj.flag === false) { 135 if (rectObj.flag === 'false' || rectObj.flag === false) {
133 - loger.error(`会议密码校验-失败.`); 136 + loger.error(`课堂密码校验-失败.`);
134 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_PASSWORD_WRONG); 137 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_PASSWORD_WRONG);
135 return; 138 return;
136 } 139 }
137 if (rectObj.flag === 'true' || rectObj.flag === true) { 140 if (rectObj.flag === 'true' || rectObj.flag === true) {
138 - loger.log(`会议密码校验-成功.`); 141 + loger.log(`课堂密码校验-成功.`);
139 this.sendMD5Checking(); 142 this.sendMD5Checking();
140 return; 143 return;
141 } 144 }
142 - loger.error(`会议密码校验-协议异常.`, rectObj); 145 + loger.error(`课堂密码校验-协议异常.`, rectObj);
143 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PROTOCOL); 146 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PROTOCOL);
144 }) 147 })
145 .catch(err => { 148 .catch(err => {
146 - loger.error(`会议密码校验-异常.状态码:${err}`); 149 + loger.error(`课堂密码校验-异常.状态码:${err}`);
147 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FAILED); 150 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FAILED);
148 }); 151 });
149 } 152 }
@@ -182,7 +185,7 @@ class Sass extends Emiter { @@ -182,7 +185,7 @@ class Sass extends Emiter {
182 GlobalConfig.maxAudioChannels=confInfo.maxAudioChannels; 185 GlobalConfig.maxAudioChannels=confInfo.maxAudioChannels;
183 GlobalConfig.maxMediaChannels=confInfo.maxMediaChannels;*/ 186 GlobalConfig.maxMediaChannels=confInfo.maxMediaChannels;*/
184 loger.log('MD5校验完成'); 187 loger.log('MD5校验完成');
185 - console.log(ret); 188 + loger.log(ret);
186 this._emit(Sass.SUCCESS, ret); 189 this._emit(Sass.SUCCESS, ret);
187 } else { 190 } else {
188 loger.log('MD5校验-失败.'); 191 loger.log('MD5校验-失败.');
@@ -196,7 +199,7 @@ class Sass extends Emiter { @@ -196,7 +199,7 @@ class Sass extends Emiter {
196 }); 199 });
197 } 200 }
198 201
199 - // 获取会议基本详情------------------------------------------------------------------------------------ 202 + // 获取课堂基本详情------------------------------------------------------------------------------------
200 getClassDetail() { 203 getClassDetail() {
201 let url = `http://${confInfo.portal}/3m/meeting/getClassH5.do?classNumber=${confInfo.classId}`; 204 let url = `http://${confInfo.portal}/3m/meeting/getClassH5.do?classNumber=${confInfo.classId}`;
202 loger.log('获取Class详情.', url); 205 loger.log('获取Class详情.', url);
@@ -227,7 +230,7 @@ class Sass extends Emiter { @@ -227,7 +230,7 @@ class Sass extends Emiter {
227 }); 230 });
228 } 231 }
229 232
230 - //获取课堂会议的完整信息-------------------------------------------------------------------------------- 233 + //获取课堂课堂的完整信息--------------------------------------------------------------------------------
231 getClassParam() { 234 getClassParam() {
232 /* 235 /*
233 参数 (application/x-www-form-urlencoded): 236 参数 (application/x-www-form-urlencoded):
@@ -246,10 +249,10 @@ class Sass extends Emiter { @@ -246,10 +249,10 @@ class Sass extends Emiter {
246 meetingNumber String 课堂号 对应的是classId 249 meetingNumber String 课堂号 对应的是classId
247 */ 250 */
248 var timestamp = new Date().getTime(); 251 var timestamp = new Date().getTime();
249 - var authId = MD5(confInfo.classId + "" + timestamp);//课堂号+时间戳 的字符串,转成MD5  
250 - let url = `http://${confInfo.portal}/3m/api/meeting/detail.do?meetingNumber=${confInfo.classId}&timestamp=${timestamp}&authId=${authId}`;  
251 - loger.log('5.获取课堂会议的完整信息 ');  
252 - console.log(url); 252 + var authId = MD5(GlobalConfig.classId + "" + timestamp);//课堂号+时间戳 的字符串,转成MD5
  253 + let url = `http://${GlobalConfig.portal}/3m/api/meeting/detail.do?meetingNumber=${GlobalConfig.classId}&timestamp=${timestamp}&authId=${authId}`;
  254 + loger.log('5.获取课堂课堂的完整信息 ');
  255 + loger.log(url);
253 fetch(url, { 256 fetch(url, {
254 timeout: 5000 257 timeout: 5000
255 }) 258 })
@@ -257,7 +260,7 @@ class Sass extends Emiter { @@ -257,7 +260,7 @@ class Sass extends Emiter {
257 if (ret.ok) { 260 if (ret.ok) {
258 return ret.json(); 261 return ret.json();
259 } else { 262 } else {
260 - loger.error(`获取课堂会议的完整信息-网络异常.状态码:${ret.status}`); 263 + loger.error(`获取课堂课堂的完整信息-网络异常.状态码:${ret.status}`);
261 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML); 264 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
262 265
263 throw ''; 266 throw '';
@@ -265,15 +268,15 @@ class Sass extends Emiter { @@ -265,15 +268,15 @@ class Sass extends Emiter {
265 }) 268 })
266 .then(ret => { 269 .then(ret => {
267 if (ret.code === 0) { 270 if (ret.code === 0) {
268 - loger.log('获取课堂会议的完整信息完成'); 271 + loger.log('获取课堂课堂的完整信息完成');
269 this._emit(Sass.CLASS_GET_CLASS_PARAM, ret); 272 this._emit(Sass.CLASS_GET_CLASS_PARAM, ret);
270 } else { 273 } else {
271 - loger.warn('获取课堂会议的完整信息 失败.'); 274 + loger.warn('获取课堂课堂的完整信息 失败.');
272 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML); 275 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
273 } 276 }
274 }) 277 })
275 .catch(err => { 278 .catch(err => {
276 - loger.error(`获取课堂会议的完整信息异常.状态码:${err}`); 279 + loger.error(`获取课堂课堂的完整信息异常.状态码:${err}`);
277 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML); 280 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
278 }); 281 });
279 } 282 }
@@ -291,6 +294,10 @@ class Sass extends Emiter { @@ -291,6 +294,10 @@ class Sass extends Emiter {
291 0 成功, 1 验证信息错误 294 0 成功, 1 验证信息错误
292 */ 295 */
293 sassDeleteDocument(_param) { 296 sassDeleteDocument(_param) {
  297 + if(GlobalConfig.isRecordPlayBack){
  298 + loger.log('录制回放中,能删除文档');
  299 + return;
  300 + }
294 var timestamp = new Date().getTime(); 301 var timestamp = new Date().getTime();
295 var authId = MD5(_param.docId + "" + _param.classId + "" + timestamp);// docId+classId+timestamp的字符串,转成MD5 302 var authId = MD5(_param.docId + "" + _param.classId + "" + timestamp);// docId+classId+timestamp的字符串,转成MD5
296 let url = `http://${confInfo.portal}/3m/api/document/deleteRelation.do?docId=${_param.docId}&classId=${confInfo.classId}&timestamp=${timestamp}&authId=${authId}`; 303 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 { @@ -337,6 +344,10 @@ class Sass extends Emiter {
337 code 0 成功 1 课堂号为空 2 无效的课堂号 3 验证信息错误*/ 344 code 0 成功 1 课堂号为空 2 无效的课堂号 3 验证信息错误*/
338 345
339 saveClassStatusInfo(_param) { 346 saveClassStatusInfo(_param) {
  347 + if(GlobalConfig.isRecordPlayBack){
  348 + loger.log('录制回放中,不需要保存课堂信息');
  349 + return;
  350 + }
340 //{"classStatusInfo":classStatusInfo} 351 //{"classStatusInfo":classStatusInfo}
341 var timestamp = new Date().getTime(); 352 var timestamp = new Date().getTime();
342 var authId = MD5(confInfo.classId + "" + timestamp);// (classId+timestamp)的字符串,转成MD5 353 var authId = MD5(confInfo.classId + "" + timestamp);// (classId+timestamp)的字符串,转成MD5
@@ -383,24 +394,28 @@ class Sass extends Emiter { @@ -383,24 +394,28 @@ class Sass extends Emiter {
383 394
384 //保存录制的信息,主要是录制文件的名称,必须和MCU录制的文件名相同 395 //保存录制的信息,主要是录制文件的名称,必须和MCU录制的文件名相同
385 saveClassRecordContrlInfo(_param) { 396 saveClassRecordContrlInfo(_param) {
  397 + if(GlobalConfig.isRecordPlayBack){
  398 + loger.log('录制回放中,不需要保存');
  399 + return;
  400 + }
386 loger.log('保存开始录制信息'); 401 loger.log('保存开始录制信息');
387 - let key = "3mang123A";  
388 - let siteID = GlobalConfig.siteId; 402 + let key = "3mang123A";
  403 + let siteID = GlobalConfig.siteId;
389 let meetingID = GlobalConfig.classId; 404 let meetingID = GlobalConfig.classId;
390 - let userID = GlobalConfig.userId;  
391 - let userName = GlobalConfig.userName; 405 + let userID = GlobalConfig.userId;
  406 + let userName = GlobalConfig.userName;
392 let meetingName = GlobalConfig.className; 407 let meetingName = GlobalConfig.className;
393 - let startTime =GlobalConfig.classBeginTime;  
394 - let endTime = GlobalConfig.classEndTime;  
395 - let playUrl = "";  
396 - let streamName = GlobalConfig.recordFileName;  
397 - let confRecordFileName=GlobalConfig.recordFileName;  
398 - let downloadUrl = "";  
399 - let recordStatus = GlobalConfig.classStatus;  
400 - let recordTimestamp =GlobalConfig.classTimestamp; 408 + let startTime = GlobalConfig.classBeginTime;
  409 + let endTime = GlobalConfig.classEndTime;
  410 + let playUrl = "";
  411 + let streamName = GlobalConfig.recordFileName;
  412 + let confRecordFileName = GlobalConfig.recordFileName;
  413 + let downloadUrl = "";
  414 + let recordStatus = GlobalConfig.classStatus;
  415 + let recordTimestamp = GlobalConfig.classTimestamp;
401 416
402 - let timestamp = new Date().getTime();;  
403 - let authId = MD5(key + siteID + meetingID + timestamp); 417 + let timestamp = new Date().getTime();
  418 + let authId = MD5(key + siteID + meetingID + timestamp);
404 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}`; 419 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}`;
405 loger.log('saveClassRecordContrlInfo', url); 420 loger.log('saveClassRecordContrlInfo', url);
406 421
@@ -420,7 +435,7 @@ class Sass extends Emiter { @@ -420,7 +435,7 @@ class Sass extends Emiter {
420 loger.log('保存开始录制信息 完成'); 435 loger.log('保存开始录制信息 完成');
421 this._emit(Sass.CLASS_SAVE_RECORD_INFO_SUCCESS, _param); 436 this._emit(Sass.CLASS_SAVE_RECORD_INFO_SUCCESS, _param);
422 } else { 437 } else {
423 - loger.warn('保存开始录制信息 失败.',ret); 438 + loger.warn('保存开始录制信息 失败.', ret);
424 } 439 }
425 }) 440 })
426 .catch(err => { 441 .catch(err => {
@@ -428,7 +443,6 @@ class Sass extends Emiter { @@ -428,7 +443,6 @@ class Sass extends Emiter {
428 }); 443 });
429 444
430 } 445 }
431 -  
432 } 446 }
433 447
434 Sass.prototype.SUCCESS = Sass.SUCCESS = 'Sass_success'; 448 Sass.prototype.SUCCESS = Sass.SUCCESS = 'Sass_success';
@@ -437,8 +451,8 @@ Sass.prototype.CLASS_GET_CLASS_PARAM = Sass.CLASS_GET_CLASS_PARAM = 'sass_class_ @@ -437,8 +451,8 @@ Sass.prototype.CLASS_GET_CLASS_PARAM = Sass.CLASS_GET_CLASS_PARAM = 'sass_class_
437 Sass.prototype.CLASS_GET_CLASS_DETAIL = Sass.CLASS_GET_CLASS_DETAIL = 'sass_class_getClassDetail_message'; 451 Sass.prototype.CLASS_GET_CLASS_DETAIL = Sass.CLASS_GET_CLASS_DETAIL = 'sass_class_getClassDetail_message';
438 Sass.prototype.DELETE_DOCUMENT_SUCCESS = Sass.DELETE_DOCUMENT_SUCCESS = 'sass_class_deleteDocumentSuccess_message';//删除文档成功 452 Sass.prototype.DELETE_DOCUMENT_SUCCESS = Sass.DELETE_DOCUMENT_SUCCESS = 'sass_class_deleteDocumentSuccess_message';//删除文档成功
439 453
440 -Sass.prototype.CLASS_SAVE_STATUS_INFO_SUCCESS = Sass.CLASS_SAVE_STATUS_INFO_SUCCESS = 'sass_class_saveClassStatusInfoSuccess_message';//保存会议状态信息  
441 -Sass.prototype.CLASS_SAVE_RECORD_INFO_SUCCESS = Sass.CLASS_SAVE_RECORD_INFO_SUCCESS = 'sass_class_saveClassRecordInfoSuccess_message';//保存录制会议信息 454 +Sass.prototype.CLASS_SAVE_STATUS_INFO_SUCCESS = Sass.CLASS_SAVE_STATUS_INFO_SUCCESS = 'sass_class_saveClassStatusInfoSuccess_message';//保存课堂状态信息
  455 +Sass.prototype.CLASS_SAVE_RECORD_INFO_SUCCESS = Sass.CLASS_SAVE_RECORD_INFO_SUCCESS = 'sass_class_saveClassRecordInfoSuccess_message';//保存录制课堂信息
442 456
443 457
444 export default new Sass; 458 export default new Sass;
  1 +import Emiter from 'Emiter';
  2 +import Loger from 'Loger';
  3 +import MessageTypes from 'MessageTypes';
  4 +import GlobalConfig from 'GlobalConfig';
  5 +import MD5 from "md5";
  6 +import ApeConsts from 'apes/ApeConsts';
  7 +import iphunter from 'iphunter';
  8 +import Server from "config/Server";
  9 +import fetchJsonp from 'fetch-jsonp';
  10 +
  11 +// 日志对象
  12 +const loger = Loger.getLoger('ServerCheck');
  13 +
  14 +//ip选点流程的状态
  15 +let isRequestMcuCallback = false;//是否获取最佳mcu返回
  16 +let isRequestMsCallback = false;//是否获取ms最佳返回
  17 +let isTestFromSass=false;
  18 +let isTestFromServer=false;
  19 +
  20 +let tempMcuIp="";
  21 +let tempMcuPort="";
  22 +let tempMsIp="";
  23 +let tempMsPort="";
  24 +let msDefaultPort=":1935";
  25 +let mcuDefaultPort="7777";
  26 +let speedTestPort = ':5555';//测速端口统一
  27 +
  28 +let checkMcuIpGroup =[];//储存MCU需要查询的ip数组
  29 +let checkMsIpGroup =[];//储存MCU需要查询的ip数组
  30 +class ServerCheck extends Emiter {
  31 + constructor() {
  32 + super();
  33 +
  34 + }
  35 +
  36 + //根据userIp获取ip相关的信息,参数是userIp
  37 + getUserIpInfo(token, userIp) {
  38 + //重置ip选点流程状态
  39 + isRequestMcuCallback = false;
  40 + isRequestMsCallback = false;
  41 + isTestFromSass=false;
  42 + isTestFromServer=false;
  43 + checkMcuIpGroup =[];
  44 + checkMsIpGroup =[];
  45 + let userIpInfo = new Object;
  46 + userIpInfo.ret = -1;
  47 +
  48 + let ip = userIp;
  49 + let md5Str = MD5("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3");//("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3"),转成MD5
  50 + let timestamp = new Date().getTime();
  51 + let location = `http://ipapi.ipip.net/find?addr=${ip}&sid=14&uid=5237&sig=${md5Str}&_=${timestamp}`;
  52 + loger.log('获取IP信息 ', userIp, location);
  53 +
  54 + fetchJsonp(location, {
  55 + timeout: 3000,
  56 + }).then(function (response) {
  57 + return response.json()
  58 + }).then(function (json) {
  59 + loger.log('获取IP信息返回', json)
  60 + if (json) {
  61 + userIpInfo.ret = json.ret;
  62 + userIpInfo.country = json.data[0];//国家
  63 + userIpInfo.province = json.data[1];//省份
  64 + userIpInfo.city = json.data[2];//城市
  65 + userIpInfo.isp = json.data[4];//运营商
  66 + }
  67 + this.serverGetUserIpInfoCallback(userIpInfo);
  68 + }.bind(this)).catch(function (ex) {
  69 + loger.log('获取IP信息失败', ex.message)
  70 + this.serverGetUserIpInfoCallback(userIpInfo);
  71 + }.bind(this));
  72 + }
  73 +
  74 + //获取ip信息返回
  75 + serverGetUserIpInfoCallback(userIpInfo) {
  76 + loger.log("获取IP详情,开始处理", userIpInfo);
  77 + if (userIpInfo.ret == "ok") {
  78 + GlobalConfig.country = userIpInfo.country;//国家
  79 + GlobalConfig.city = userIpInfo.city;//城市
  80 + GlobalConfig.province = userIpInfo.province;//服务商
  81 + GlobalConfig.isp = userIpInfo.isp;//服务商
  82 + loger.log("获取ip详情成功,country:" + GlobalConfig.country + ",city:" + GlobalConfig.city + ",isp:" + GlobalConfig.isp);
  83 + this._chooseBestIpFromServer();
  84 + }
  85 + else {
  86 + loger.log("获取ip详情失败");
  87 + this._chooseBestIpFromSassParam();
  88 + }
  89 + }
  90 +
  91 + //从IPIP服务列表中选择最快的IP
  92 + _chooseBestIpFromServer() {
  93 + loger.log("从Server服务列表中选择最快的IP");
  94 + isRequestMcuCallback=false;
  95 + isRequestMsCallback=false;
  96 + isTestFromServer=true;
  97 + isTestFromSass=false;
  98 +
  99 + //country, province, ctiy, isp, jsona
  100 + checkMcuIpGroup =this._returnServerMCU(
  101 + GlobalConfig.country,
  102 + GlobalConfig.province,
  103 + GlobalConfig.city,
  104 + GlobalConfig.isp,
  105 + Server.serverList);
  106 +
  107 + checkMsIpGroup = this._returnServerMS(
  108 + GlobalConfig.country,
  109 + GlobalConfig.province,
  110 + GlobalConfig.city,
  111 + GlobalConfig.isp,
  112 + Server.serverList);
  113 +
  114 + let mcuArr=[];
  115 + let msArr=[];
  116 + for(let i in checkMcuIpGroup){
  117 + if(checkMcuIpGroup[i]){
  118 + mcuArr.push(checkMcuIpGroup[i].ip+speedTestPort);
  119 + }
  120 + }
  121 + for(let k in checkMsIpGroup){
  122 + if(checkMsIpGroup[k]){
  123 + msArr.push(checkMsIpGroup[k].ip+speedTestPort);
  124 + }
  125 + }
  126 + this.getBestMcuServer(mcuArr);
  127 + this.getBestMsServer(msArr);
  128 + }
  129 + //从Sass返回的msList mcuList中选点
  130 + _chooseBestIpFromSassParam() {
  131 + loger.log("从Sass服务列表中选择最快的IP");
  132 + isRequestMcuCallback = false;
  133 + isRequestMsCallback = false;
  134 + isTestFromSass=false;
  135 + isTestFromServer=false;
  136 + checkMcuIpGroup =GlobalConfig.mcuList;
  137 + checkMsIpGroup =GlobalConfig.msList;
  138 + //MCU
  139 + let mcuIpGroup = [];
  140 + for (let i = 0; i < checkMcuIpGroup.length; i++) {
  141 + let ipPort = checkMcuIpGroup[i].ip+speedTestPort;
  142 + mcuIpGroup.push(ipPort)
  143 + }
  144 + this.getBestMcuServer(mcuIpGroup);
  145 +
  146 + //MS
  147 + let msIpGroup = [];
  148 + for (let k = 0; k < checkMsIpGroup.length; k++) {
  149 + let ipPort = checkMsIpGroup[k].ip+speedTestPort;
  150 + msIpGroup.push(ipPort)
  151 + }
  152 + this.getBestMsServer(msIpGroup);
  153 + }
  154 +
  155 +
  156 + //获取最快的MCU服务器地址,参数是一个ip数组
  157 + getBestMcuServer(_param) {
  158 + loger.log('开始MCU选点 ', _param);
  159 + if(_param==null||_param.length<1){
  160 + this._getBestMcuServerCallbackHandler("")
  161 + return;
  162 + }
  163 + iphunter(_param, function (fatest_ip_response) {
  164 + if (!fatest_ip_response) {
  165 + loger.warn('getBestMcuServer -> nothing!');
  166 + this._getBestMcuServerCallbackHandler("")
  167 + } else {
  168 + //loger.log('getBestMcuServer done -> ', fatest_ip_response);
  169 + this._getBestMcuServerCallbackHandler(fatest_ip_response)
  170 + }
  171 + }.bind(this), 3000);
  172 + }
  173 +
  174 + //获取最快的MS服务器地址,参数是一个ip数组
  175 + getBestMsServer(_param) {
  176 + loger.log('开始MS选点 ', _param);
  177 + if(_param==null||_param.length<1){
  178 + this._getBestMsServerCallbackHandler("")
  179 + return;
  180 + }
  181 + iphunter(_param, function (fatest_ip_response) {
  182 + if (!fatest_ip_response) {
  183 + loger.warn('getBestMsServer -> nothing!');
  184 + this._getBestMsServerCallbackHandler("");
  185 + } else {
  186 + //loger.log('getBestMsServer done -> ', fatest_ip_response);
  187 + this._getBestMsServerCallbackHandler(fatest_ip_response);
  188 + }
  189 + }.bind(this), 3000);
  190 + }
  191 +
  192 + _getBestMcuServerCallbackHandler(_data) {
  193 + loger.log("MCU选点返回1", _data);
  194 + if (isRequestMcuCallback) {
  195 + loger.log("MCU选点,已经有返回");
  196 + return;
  197 + }
  198 + isRequestMcuCallback = true;
  199 + if (_data) {
  200 + let server = _data.split(":");
  201 + if (server[0]) {
  202 + tempMcuIp= server[0];
  203 + }
  204 + tempMcuPort=mcuDefaultPort;
  205 + for(let i=0;i<checkMcuIpGroup.length;i++){
  206 + if(tempMcuIp==checkMcuIpGroup[i].ip){
  207 + tempMcuPort=checkMcuIpGroup[i].port||mcuDefaultPort;
  208 + break;
  209 + }
  210 + }
  211 + }
  212 + loger.log("MCU选点返回2",tempMcuIp,tempMcuPort);
  213 + this._startConnectMcu();
  214 + }
  215 +
  216 + _getBestMsServerCallbackHandler(_data) {
  217 + loger.log("MS选点返回1", _data);
  218 + if (isRequestMsCallback) {
  219 + loger.log("_getBestMsServerCallbackHandler,已经有返回");
  220 + return;
  221 + }
  222 + isRequestMsCallback = true;
  223 + if (_data) {
  224 + let server = _data.split(":");
  225 + if (server[0]) {
  226 + tempMsIp= server[0];
  227 + }
  228 + tempMsPort=msDefaultPort;
  229 + for(let i=0;i<checkMsIpGroup.length;i++){
  230 + if(tempMsPort==checkMsIpGroup[i].ip){
  231 + tempMsPort=checkMsIpGroup[i].port||msDefaultPort;
  232 + break;
  233 + }
  234 + }
  235 + }
  236 + loger.log("MS选点返回2", tempMsIp,tempMsPort);
  237 + this._startConnectMcu();
  238 + }
  239 +
  240 + //ip选点结束,开始连接MCU
  241 + _startConnectMcu() {
  242 + if (isRequestMcuCallback && isRequestMsCallback) {
  243 + if (isTestFromServer && !isTestFromSass) {
  244 + //从Server服务列表中选点结束,如果没有选到合适的,从Sass的列表中获取
  245 + if(!tempMcuIp||!tempMsIp){
  246 + this._chooseBestIpFromSassParam();
  247 + }else {
  248 + GlobalConfig.MCUServerIP=tempMcuIp;
  249 + GlobalConfig.MCUServerPort=tempMcuPort;
  250 + GlobalConfig.MSServerIP=tempMsIp;
  251 + GlobalConfig.MSServerPort=tempMsPort;
  252 + loger.log("Server选点完成", "mcu-->",GlobalConfig.MCUServerIP,GlobalConfig.MCUServerPort,"ms---->",GlobalConfig.MSServerIP,GlobalConfig.MSServerPort);
  253 + this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
  254 + }
  255 + } else {
  256 + //从Sass返回的服务列表中选点结束
  257 + if(tempMcuIp){
  258 + GlobalConfig.MCUServerIP=tempMcuIp;
  259 + GlobalConfig.MCUServerPort=tempMcuPort;
  260 + }
  261 + if(tempMsIp){
  262 + GlobalConfig.MSServerIP=tempMsIp;
  263 + GlobalConfig.MSServerPort=tempMsPort;
  264 + }
  265 + loger.log("Sass选点完成", "mcu-->",GlobalConfig.MCUServerIP,GlobalConfig.MCUServerPort,"ms---->",GlobalConfig.MSServerIP,GlobalConfig.MSServerPort);
  266 + this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
  267 + }
  268 + } else {
  269 + loger.warn("_startConnectMcu->正在选点", isRequestMcuCallback, isRequestMsCallback);
  270 + }
  271 + }
  272 +
  273 + //检测MCU连接地址
  274 + _returnServerMCU(country, province, ctiy, isp, jsona) {
  275 + let countryData=jsona.MCU[country];
  276 + //按country没有查找到就返回default
  277 + if(!countryData){
  278 + countryData=jsona.MCU.default;
  279 + loger.log("_returnServerMCU->countryData->default",countryData);
  280 + return countryData;
  281 + }
  282 +
  283 + if(country!="中国"){
  284 + loger.log("_returnServerMCU->countryData",countryData);
  285 + return countryData;
  286 + }
  287 +
  288 + //中国的需要细分
  289 + //按isp查找
  290 + let ispData=countryData.isp[isp];
  291 + //isp查找到就返回
  292 + if(ispData){
  293 + loger.log("_returnServerMCU->ispData",ispData);
  294 + return ispData;
  295 + }
  296 +
  297 + //isp没查找到,用province
  298 + let provinceData=countryData.province[province];
  299 + //用province查找到就返回
  300 + if(provinceData){
  301 + loger.log("_returnServerMCU->provinceData",provinceData);
  302 + return provinceData;
  303 + }
  304 +
  305 +
  306 + //isp province都没有,使用default
  307 + let defaultData=countryData.default
  308 + if(defaultData){
  309 + loger.log("_returnServerMCU->defaultData",defaultData);
  310 + return defaultData;
  311 + }else {
  312 + loger.log("_returnServerMCU->defaultData","");
  313 + return [];
  314 + }
  315 + return [];
  316 + }
  317 +
  318 + //检测MS连接地址
  319 + //Config.ipInfo
  320 + _returnServerMS(country, province, ctiy, isp, jsona) {
  321 + let countryData=jsona.MS[country];
  322 + //按country没有查找到就返回default
  323 + if(!countryData){
  324 + countryData=jsona.MS.default;
  325 + loger.log("_returnServerMS->countryData->default",countryData);
  326 + return countryData;
  327 + }
  328 +
  329 + if(country!="中国"){
  330 + loger.log("_returnServerMS->countryData",countryData);
  331 + return countryData;
  332 + }
  333 +
  334 + //中国的需要细分
  335 + //按isp查找
  336 + let ispData=countryData.isp[isp];
  337 + //isp查找到就返回
  338 + if(ispData){
  339 + loger.log("_returnServerMS->ispData",ispData);
  340 + return ispData;
  341 + }
  342 +
  343 + //isp没查找到,用province
  344 + let provinceData=countryData.province[province];
  345 + //用province查找到就返回
  346 + if(provinceData){
  347 + loger.log("_returnServerMS->provinceData",provinceData);
  348 + return provinceData;
  349 + }
  350 +
  351 +
  352 + //isp province都没有,使用default
  353 + let defaultData=countryData.default
  354 + if(defaultData){
  355 + loger.log("_returnServerMS->defaultData",defaultData);
  356 + return defaultData;
  357 + }else {
  358 + loger.log("_returnServerMS->defaultData","");
  359 + return [];
  360 + }
  361 +
  362 + return [];
  363 + }
  364 +}
  365 +
  366 +ServerCheck.prototype.SEVER_CHECK_BEST_IP_SUCCESS = ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS = 'severCheck_checkBestIpSuccess_message';//获取最快的MS地址
  367 +export default new ServerCheck;
  368 +
@@ -32,6 +32,7 @@ class TimerCounter { @@ -32,6 +32,7 @@ class TimerCounter {
32 } 32 }
33 //停止 33 //停止
34 stopTimer(){ 34 stopTimer(){
  35 + if(!this.isStart) return;
35 console.log("stopTimer",this.counter); 36 console.log("stopTimer",this.counter);
36 this.isStart=false; 37 this.isStart=false;
37 this.timerClear(); 38 this.timerClear();
@@ -15,364 +15,373 @@ @@ -15,364 +15,373 @@
15 15
16 import pdu from 'pdus'; 16 import pdu from 'pdus';
17 import Emiter from 'Emiter'; 17 import Emiter from 'Emiter';
18 -import mcu from 'mcu'; 18 +import McuObj from 'mcu';
19 import Loger from 'Loger'; 19 import Loger from 'Loger';
20 import MessageTypes from 'MessageTypes'; 20 import MessageTypes from 'MessageTypes';
21 import ApeConsts from './ApeConsts'; 21 import ApeConsts from './ApeConsts';
22 import ArrayBufferUtil from 'libs/ArrayBufferUtil'; 22 import ArrayBufferUtil from 'libs/ArrayBufferUtil';
23 import PduConsts from 'pdus/PduConsts'; 23 import PduConsts from 'pdus/PduConsts';
24 import GlobalConfig from 'GlobalConfig'; 24 import GlobalConfig from 'GlobalConfig';
  25 +import RecordPlayBackParse from 'RecordPlayBackParse';
25 26
26 // 日志对象 27 // 日志对象
27 const loger = Loger.getLoger('Ape'); 28 const loger = Loger.getLoger('Ape');
28 29
29 export default class Ape extends Emiter { 30 export default class Ape extends Emiter {
30 - constructor(  
31 - session_id,  
32 - session_name,  
33 - session_tag  
34 - ) {  
35 - super();  
36 - this._session_id = session_id;  
37 - this._channel_id = session_id; // session_id === channel_id  
38 - this._session_name = session_name;  
39 - this._session_tag = session_tag;  
40 - this._session_channels = {};  
41 - this._adapter_pdu = new pdu['RCAdapterPdu'];  
42 - this._classInfo = null;  
43 - this._rCArrayBufferUtil = ArrayBufferUtil;  
44 - this._apeDelayed = false;  
45 - this._apeDelayedMsgs = [];  
46 - this._apeDelayedTimer = 0;  
47 -  
48 - //Ape 通用消息处理  
49 - this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));  
50 - this.on(pdu.RCPDU_CHANNEL_JOIN_RESPONSE, this._joinChannelHandler.bind(this));  
51 - this.on(pdu.RCPDU_REG_ADAPTER, this._pduMessageHandler.bind(this));  
52 -  
53 - //先收到onJoinSessionHandlerSuccess 后收到 onJoinChannelHandlerSuccess  
54 -  
55 - // 监听底层MCU会议  
56 - this.mcu = mcu;  
57 - this.mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuConferenceJoinSuccessHandler.bind(this));  
58 - this.mcu.registerApe(this);  
59 - }  
60 -  
61 - regResponsePduHandler() {  
62 -  
63 - }  
64 -  
65 - // 消息处理  
66 - _pduMessageHandler(regBuffer) {  
67 - //loger.log("RCPDU_REG_ADAPTER==============================");  
68 - if (this._apeDelayed) {  
69 - // this._apeDelayedMsgs.push(regBuffer);  
70 - // this._apeDelayedStart();  
71 - setTimeout(() => {  
72 - this._pduRegAdapterHandler(regBuffer);  
73 - },GlobalConfig.mcuDelay|| 12000);  
74 - return; 31 + constructor(session_id,
  32 + session_name,
  33 + session_tag) {
  34 + super();
  35 + this._session_id = session_id;
  36 + this._channel_id = session_id; // session_id === channel_id
  37 + this._session_name = session_name;
  38 + this._session_tag = session_tag;
  39 + this._session_channels = {};
  40 + this._adapter_pdu = new pdu['RCAdapterPdu'];
  41 + this._classInfo = null;
  42 + this._rCArrayBufferUtil = ArrayBufferUtil;
  43 + this._apeDelayed = false;
  44 + this._apeDelayedMsgs = [];
  45 + this._apeDelayedTimer = 0;
  46 +
  47 + //Ape 通用消息处理
  48 + this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
  49 + this.on(pdu.RCPDU_CHANNEL_JOIN_RESPONSE, this._joinChannelHandler.bind(this));
  50 + this.on(pdu.RCPDU_REG_ADAPTER, this._pduMessageHandler.bind(this));
  51 +
  52 + //先收到onJoinSessionHandlerSuccess 后收到 onJoinChannelHandlerSuccess
  53 +
  54 + // 监听底层MCU课堂
  55 + this.mcu = McuObj;
  56 + this.mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuConferenceJoinSuccessHandler.bind(this));
  57 + this.mcu.registerApe(this);
  58 +
  59 + //录制回放
  60 + this.recordPlayBackParse = RecordPlayBackParse;
  61 + this.recordPlayBackParse.on(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, this._joinRecordPlaybackSuccessHandler.bind(this));
  62 + this.recordPlayBackParse.registerApe(this);
  63 +
75 } 64 }
76 - this._pduRegAdapterHandler(regBuffer);  
77 - }  
78 -  
79 - // _apeDelayedStart() {  
80 - // if (this._apeDelayed && !this._apeDelayedTimer) {  
81 - // this._apeDelayedTimer = setInterval(this._delayedMsgHandler.bind(this), this._classInfo['mcuDelay'] || 10000);  
82 - // }  
83 - // }  
84 -  
85 - // _apeDelayedStop() {  
86 - // clearInterval(this._apeDelayedTimer);  
87 - // this._apeDelayedTimer = 0;  
88 - // }  
89 -  
90 - // // 延迟消息处理  
91 - // _delayedMsgHandler() {  
92 - // if (this._apeDelayedMsgs.length) {  
93 - // this._pduRegAdapterHandler(this._apeDelayedMsgs.pop());  
94 - // if (!this._apeDelayedMsgs.length) this._apeDelayedStop();  
95 - // }  
96 - // }  
97 -  
98 - // 数据同步处理  
99 - _pduRegAdapterHandler(regBuffer) {  
100 - let regPdu = pdu['RCAdapterPdu'].decode(regBuffer);  
101 - let regItems = regPdu.item;  
102 - let regItemSize = regItems.length;  
103 - //loger.log(this._session_name + '数据同步消息');  
104 - loger.log(this._session_name + '数据同步消息.同步条数', regItemSize);  
105 - //console.log(regPdu);  
106 -  
107 - for (var i = 0; i < regItemSize; ++i) {  
108 - let regItem = regItems[i];  
109 - let regItemType = regItem.type;  
110 - let regItemData = regItem.itemData;  
111 -  
112 - //根据数据包中的type处理数据是否同步  
113 -  
114 - if (pdu.RCPDU_REG_UPDATE_OBJ !== regItemType) {  
115 - if (pdu.RCPDU_REG_RESPONSE_OBJ == regItemType) {  
116 - let regResponsePdu = pdu['RCRegistryResponseObjPdu'].decode(regItemData);  
117 - this.regResponsePduHandler(regResponsePdu);  
118 - }  
119 - // 只处理两种类型  
120 - continue;  
121 - }  
122 -  
123 - //具体的数据包  
124 - let regUpdatedItem = pdu['RCRegistryUpdateObjPdu'].decode(regItemData);  
125 - let sub_type = regUpdatedItem.subType;  
126 - let object_id = regUpdatedItem.objId;  
127 - let user_data = regUpdatedItem.userData;  
128 -  
129 - loger.log('REG OBJECT EVENT ->', pdu.id2type(sub_type));  
130 - switch (sub_type) {  
131 - case pdu.RCPDU_REG_ROSTER_INSERT_PDU:  
132 - let rosterInsertData = pdu['RCRegstryRosterInsertItemPdu'].decode(user_data);  
133 - let rosterInsertItems = rosterInsertData.items;  
134 - let rosterInsertItemsLen = rosterInsertItems.length;  
135 - for (let i = 0; i < rosterInsertItemsLen; ++i) {  
136 - let record = rosterInsertItems[i];  
137 - let recordId = record.item_id;  
138 - let recordData = pdu['RCNodeInfoRecordPdu'].decode(record.item_data);  
139 - this.rosterInsertHandler(recordId, recordData);  
140 - }  
141 - break;  
142 - case pdu.RCPDU_REG_ROSTER_DELETE_PDU:  
143 - let rosterDelData = pdu['RCRegistryRosterDeleteItemPdu'].decode(user_data);  
144 - this.rosterDelHandler(rosterDelData.nodeId);  
145 - break;  
146 - case pdu.RCPDU_REG_ROSTER_UPDATE_PDU:  
147 - let rosterUpdateData = pdu['RCRegistryRosterUpdateItemPdu'].decode(user_data);  
148 - let rosterUpdateItems = rosterUpdateData.items;  
149 - let rosterUpdateItemsLen = rosterUpdateItems.length;  
150 - for (let i = 0; i < rosterUpdateItemsLen; ++i) {  
151 - let node = rosterUpdateItems[i];  
152 - let nodeId = node.nodeId;  
153 - let nodeData = pdu['RCNodeInfoRecordPdu'].decode(node.nodeData);  
154 - this.rosterUpdateHandler(nodeId, nodeData);  
155 - }  
156 - break;  
157 - case pdu.RCPDU_REG_TABLE_INSERT_PDU:  
158 - let tableInsertData = pdu['RCRegistryTableInsertItemPdu'].decode(user_data);  
159 - let tableInsertItems = tableInsertData.items;  
160 - let tableInsertItemsLen = tableInsertItems.length;  
161 - for (let i = 0; i < tableInsertItemsLen; ++i) {  
162 - let insertItem = tableInsertItems[i];  
163 - //loger.log("insertItem",insertItem);  
164 - this.tableInsertHandler(insertItem.owner, insertItem.itemIdx, insertItem.itemData); 65 +
  66 + regResponsePduHandler() {
  67 +
  68 + }
  69 +
  70 + //停止APE一切操作
  71 + stopApe() {
  72 + loger.log("stopApe==============================");
  73 + }
  74 +
  75 + // 消息处理
  76 + _pduMessageHandler(regBuffer,_seekTime) {
  77 + let seekTime=_seekTime||0;//这个只有在录制回放的时候才有
  78 + //loger.log("RCPDU_REG_ADAPTER============seekTime",seekTime);
  79 + if (this._apeDelayed) {
  80 + // this._apeDelayedMsgs.push(regBuffer);
  81 + // this._apeDelayedStart();
  82 + setTimeout(() => {
  83 + this._pduRegAdapterHandler(regBuffer,seekTime);
  84 + }, GlobalConfig.mcuDelay || 2000);
  85 + return;
165 } 86 }
166 - break;  
167 - case pdu.RCPDU_REG_TABLE_DELETE_PDU:  
168 - let tableDeleteData = pdu['RCRegistryTableDeleteItemPdu'].decode(user_data);  
169 - //console.log("tableDeleteData",object_id,tableDeleteData);  
170 - this.tableDeleteHandler(object_id, tableDeleteData);  
171 - break;  
172 - case pdu.RCPDU_REG_TABLE_UPDATE_PDU:  
173 - let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data);  
174 - let tableUpdateItems = tableUpdateData.items;  
175 - let tableUpdateItemsLen= tableUpdateItems.length;  
176 - loger.log("RCRegistryTableUpdateItemPdu "+tableUpdateItemsLen);  
177 - console.log(tableUpdateData);  
178 -  
179 - for (let i = 0; i < tableUpdateItemsLen; ++i) {  
180 - let tableItem = tableUpdateItems[i];  
181 - this.tableUpdateHandler(tableItem.owner, tableItem.itemIdx, tableItem.itemData); 87 + this._pduRegAdapterHandler(regBuffer,seekTime);
  88 + }
  89 +
  90 + // 数据同步处理
  91 + _pduRegAdapterHandler(regBuffer,seekTime) {
  92 + let regPdu = pdu['RCAdapterPdu'].decode(regBuffer);
  93 + let regItems = regPdu.item;
  94 + let regItemSize = regItems.length;
  95 + //loger.log(this._session_name + '数据同步消息');
  96 + //loger.log(this._session_name + '数据同步消息.同步条数', regItemSize,"seekTime->",seekTime);
  97 + for (var i = 0; i < regItemSize; ++i) {
  98 + let regItem = regItems[i];
  99 + let regItemType = regItem.type;
  100 + let regItemData = regItem.itemData;
  101 +
  102 + //根据数据包中的type处理数据是否同步
  103 +
  104 + if (pdu.RCPDU_REG_UPDATE_OBJ !== regItemType) {
  105 + if (pdu.RCPDU_REG_RESPONSE_OBJ == regItemType) {
  106 + let regResponsePdu = pdu['RCRegistryResponseObjPdu'].decode(regItemData);
  107 + this.regResponsePduHandler(regResponsePdu);
  108 + }
  109 + // 只处理两种类型
  110 + continue;
  111 + }
  112 +
  113 + //具体的数据包
  114 + let regUpdatedItem = pdu['RCRegistryUpdateObjPdu'].decode(regItemData);
  115 + let sub_type = regUpdatedItem.subType;
  116 + let object_id = regUpdatedItem.objId;
  117 + let user_data = regUpdatedItem.userData;
  118 +
  119 + loger.log('REG OBJECT EVENT ->', pdu.id2type(sub_type));
  120 + switch (sub_type) {
  121 + case pdu.RCPDU_REG_ROSTER_INSERT_PDU:
  122 + let rosterInsertData = pdu['RCRegstryRosterInsertItemPdu'].decode(user_data);
  123 + let rosterInsertItems = rosterInsertData.items;
  124 + let rosterInsertItemsLen = rosterInsertItems.length;
  125 + for (let i = 0; i < rosterInsertItemsLen; ++i) {
  126 + let record = rosterInsertItems[i];
  127 + let recordId = record.item_id;
  128 + let recordData = pdu['RCNodeInfoRecordPdu'].decode(record.item_data);
  129 + this.rosterInsertHandler(recordId, recordData);
  130 + }
  131 + break;
  132 + case pdu.RCPDU_REG_ROSTER_DELETE_PDU:
  133 + let rosterDelData = pdu['RCRegistryRosterDeleteItemPdu'].decode(user_data);
  134 + this.rosterDelHandler(rosterDelData.nodeId);
  135 + break;
  136 + case pdu.RCPDU_REG_ROSTER_UPDATE_PDU:
  137 + let rosterUpdateData = pdu['RCRegistryRosterUpdateItemPdu'].decode(user_data);
  138 + let rosterUpdateItems = rosterUpdateData.items;
  139 + let rosterUpdateItemsLen = rosterUpdateItems.length;
  140 + for (let i = 0; i < rosterUpdateItemsLen; ++i) {
  141 + let node = rosterUpdateItems[i];
  142 + let nodeId = node.nodeId;
  143 + let nodeData = pdu['RCNodeInfoRecordPdu'].decode(node.nodeData);
  144 + this.rosterUpdateHandler(nodeId, nodeData);
  145 + }
  146 + break;
  147 + case pdu.RCPDU_REG_TABLE_INSERT_PDU:
  148 + let tableInsertData = pdu['RCRegistryTableInsertItemPdu'].decode(user_data);
  149 + let tableInsertItems = tableInsertData.items;
  150 + let tableInsertItemsLen = tableInsertItems.length;
  151 + for (let i = 0; i < tableInsertItemsLen; ++i) {
  152 + let insertItem = tableInsertItems[i];
  153 + //loger.log("insertItem",insertItem);
  154 + this.tableInsertHandler(insertItem.owner, insertItem.itemIdx, insertItem.itemData);
  155 + }
  156 + break;
  157 + case pdu.RCPDU_REG_TABLE_DELETE_PDU:
  158 + let tableDeleteData = pdu['RCRegistryTableDeleteItemPdu'].decode(user_data);
  159 + //console.log("tableDeleteData",object_id,tableDeleteData);
  160 + this.tableDeleteHandler(object_id, tableDeleteData);
  161 + break;
  162 + case pdu.RCPDU_REG_TABLE_UPDATE_PDU:
  163 + let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data);
  164 + let tableUpdateItems = tableUpdateData.items;
  165 + let tableUpdateItemsLen = tableUpdateItems.length;
  166 + //loger.log("RCRegistryTableUpdateItemPdu " + tableUpdateItemsLen);
  167 + loger.log(tableUpdateData);
  168 +
  169 + for (let i = 0; i < tableUpdateItemsLen; ++i) {
  170 + let tableItem = tableUpdateItems[i];
  171 + this.tableUpdateHandler(tableItem.owner, tableItem.itemIdx, tableItem.itemData,seekTime);
  172 + }
  173 + break;
  174 + case pdu.RCPDU_REG_QUEUE_UPDATE_PDU:
  175 + case pdu.RCPDU_REG_QUEUE_DELETE_PDU:
  176 + case pdu.RCPDU_REG_QUEUE_INSERT_PDU:
  177 + loger.warn('REG QUEUE ARE IGNORED');
  178 + break;
  179 +
  180 + }
182 } 181 }
183 - break;  
184 - case pdu.RCPDU_REG_QUEUE_UPDATE_PDU:  
185 - case pdu.RCPDU_REG_QUEUE_DELETE_PDU:  
186 - case pdu.RCPDU_REG_QUEUE_INSERT_PDU:  
187 - loger.warn('REG QUEUE ARE IGNORED');  
188 - break;  
189 -  
190 - }  
191 } 182 }
192 - }  
193 -  
194 - rosterInsertHandler(recordId, recordData) {  
195 - loger.warn(this._session_name + ' rosterInsertHandler 应有子类具体覆盖处理.');  
196 - }  
197 - rosterUpdateHandler(nodeId, nodeData) {  
198 - loger.warn(this._session_name + ' rosterUpdateHandler 应有子类具体覆盖处理.');  
199 - }  
200 - rosterDelHandler(recordData) {  
201 - loger.warn(this._session_name + ' rosterDelHandler 应有子类具体覆盖处理.');  
202 - }  
203 - tableInsertHandler(tableId, record) {  
204 - loger.warn(this._session_name + ' tableInsertHandler 应有子类具体覆盖处理.');  
205 - }  
206 - tableUpdateHandler(ownerId, recordId, recordData) {  
207 - loger.warn(this._session_name + ' tableUpdateHandler 应有子类具体覆盖处理.');  
208 - }  
209 - tableDeleteHandler(tableId, record) {  
210 - loger.warn(this._session_name + ' tableDelHandler 应有子类具体覆盖处理.');  
211 - }  
212 - onJoinChannelHandlerSuccess(){  
213 - loger.warn(this._session_name + ' onJoinChannelHandlerSuccess 应有子类具体覆盖处理.');  
214 - }  
215 - onJoinSessionHandlerSuccess(){  
216 - loger.warn(this._session_name + ' onJoinSessionHandlerSuccess 应有子类具体覆盖处理.');  
217 - }  
218 - // 加入Session处理  
219 - _joinSessionHandler(data) {  
220 - loger.log(this._session_name, ' -> 加入Session');  
221 - this.onJoinSessionHandlerSuccess();  
222 - }  
223 -  
224 - // 加入Channel处理  
225 - _joinChannelHandler(data) {  
226 - let joinedChannel = pdu['RCChannelJoinResponsePdu'].decode(data);  
227 - if (joinedChannel.result === pdu.RET_SUCCESS) {  
228 - loger.log(this._session_name, ' -> 加入Channel成功. ChannelId', joinedChannel.requestedChannelId);  
229 - this._session_channels[joinedChannel.requestedChannelId] = ApeConsts.CJS_JOINNED;  
230 - this.onJoinChannelHandlerSuccess();  
231 - } else {  
232 - loger.log(this._session_name, ' -> 加入Channel失败.', joinedChannel); 183 +
  184 + rosterInsertHandler(recordId, recordData) {
  185 + loger.warn(this._session_name + ' rosterInsertHandler 应有子类具体覆盖处理.');
  186 + }
  187 +
  188 + rosterUpdateHandler(nodeId, nodeData) {
  189 + loger.warn(this._session_name + ' rosterUpdateHandler 应有子类具体覆盖处理.');
  190 + }
  191 +
  192 + rosterDelHandler(recordData) {
  193 + loger.warn(this._session_name + ' rosterDelHandler 应有子类具体覆盖处理.');
  194 + }
  195 +
  196 + tableInsertHandler(tableId, record) {
  197 + loger.warn(this._session_name + ' tableInsertHandler 应有子类具体覆盖处理.');
  198 + }
  199 +
  200 + tableUpdateHandler(ownerId, recordId, recordData,seekTime) {
  201 + loger.warn(this._session_name + ' tableUpdateHandler 应有子类具体覆盖处理.');
  202 + }
  203 +
  204 + tableDeleteHandler(tableId, record) {
  205 + loger.warn(this._session_name + ' tableDelHandler 应有子类具体覆盖处理.');
  206 + }
  207 +
  208 + onJoinChannelHandlerSuccess() {
  209 + loger.warn(this._session_name + ' onJoinChannelHandlerSuccess 应有子类具体覆盖处理.');
233 } 210 }
234 - }  
235 -  
236 - // 依赖的会议创建完毕 - 发起Ape加入  
237 - _mcuConferenceJoinSuccessHandler(_data) {  
238 - loger.log('创建Ape->',  
239 - 'SessionId',  
240 - this._session_id,  
241 - 'SessionName',  
242 - this._session_name,  
243 - 'SessionTag',  
244 - this._session_tag);  
245 -  
246 - // 会议依赖底层会议信息  
247 - //this._classInfo = classInfo;  
248 - this._classInfo = GlobalConfig.getClassInfo();  
249 -  
250 - var joinSessionPdu = new pdu['RCSessionJoinRequestPdu'];  
251 - joinSessionPdu.id = this._session_id;  
252 - joinSessionPdu.name = this._session_name;  
253 - joinSessionPdu.tag = this._session_tag;  
254 - joinSessionPdu.sessionData = this._adapter_pdu.toArrayBuffer();  
255 - this.sendUniform(joinSessionPdu, true);  
256 -  
257 - var joinChannelPdu = new pdu['RCChannelJoinRequestPdu'];  
258 - joinChannelPdu.initiator = this.mcu.classInfo.nodeId;  
259 - joinChannelPdu.channelId = this._session_id;  
260 - this.send(joinChannelPdu);  
261 - }  
262 -  
263 - // 注册Key对象  
264 - registerKey(id, name, tag, user_data) {  
265 - let adapterItemPdu = new pdu['RCAdapterItemPdu'];  
266 - adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_KEY;  
267 -  
268 - // pack register key pdus  
269 - let registerKeyPdu = new pdu['RCRegistryRegisterKeyPdu'];  
270 - registerKeyPdu.id = id;  
271 - registerKeyPdu.name = name;  
272 - registerKeyPdu.tag = tag;  
273 - if (user_data.length) {  
274 - registerKeyPdu.userData = user_data; 211 +
  212 + onJoinSessionHandlerSuccess() {
  213 + loger.warn(this._session_name + ' onJoinSessionHandlerSuccess 应有子类具体覆盖处理.');
275 } 214 }
276 215
277 - adapterItemPdu.itemData = registerKeyPdu.toArrayBuffer();  
278 - this._adapter_pdu.item.push(adapterItemPdu);  
279 - }  
280 -  
281 - // 注册Object对象 等同于flash中的 RCRegistryOperator  
282 - registerObj(type, id, name, tag, owner, user_data) {  
283 - let adapterItemPdu = new pdu['RCAdapterItemPdu'];  
284 - adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_OBJ;  
285 -  
286 - let registerObjPdu = new pdu['RCRegistryRegisterObjPdu'];  
287 - registerObjPdu.type = type;  
288 - registerObjPdu.objId = id;  
289 - registerObjPdu.name = name;  
290 - registerObjPdu.tag = tag;  
291 - if (owner) {  
292 - registerObjPdu.owner = owner; 216 + // 加入Session处理
  217 + _joinSessionHandler(data) {
  218 + loger.log(this._session_name, ' -> 加入Session');
  219 + this.onJoinSessionHandlerSuccess();
293 } 220 }
294 - if (user_data.length) {  
295 - registerObjPdu.userData = user_data; 221 +
  222 + // 加入Channel处理
  223 + _joinChannelHandler(data) {
  224 + let joinedChannel = pdu['RCChannelJoinResponsePdu'].decode(data);
  225 + if (joinedChannel.result === pdu.RET_SUCCESS) {
  226 + loger.log(this._session_name, ' -> 加入Channel成功. ChannelId', joinedChannel.requestedChannelId);
  227 + this._session_channels[joinedChannel.requestedChannelId] = ApeConsts.CJS_JOINNED;
  228 + this.onJoinChannelHandlerSuccess();
  229 + } else {
  230 + loger.log(this._session_name, ' -> 加入Channel失败.', joinedChannel);
  231 + }
296 } 232 }
297 233
298 - adapterItemPdu.itemData = registerObjPdu.toArrayBuffer();  
299 - this._adapter_pdu.item.push(adapterItemPdu);  
300 - }  
301 -  
302 - send(appPdu) {  
303 - loger.log('Ape发送数据NORMAL PDU');  
304 - console.log(appPdu);  
305 - //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);  
306 - if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){  
307 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);  
308 - return; 234 + // 依赖的课堂创建完毕 - 发起Ape加入
  235 + _mcuConferenceJoinSuccessHandler(_data) {
  236 + loger.log('创建Ape->',
  237 + 'SessionId',
  238 + this._session_id,
  239 + 'SessionName',
  240 + this._session_name,
  241 + 'SessionTag',
  242 + this._session_tag);
  243 +
  244 + // 课堂依赖底层课堂信息
  245 + //this._classInfo = classInfo;
  246 + this._classInfo = GlobalConfig.getClassInfo();
  247 +
  248 + var joinSessionPdu = new pdu['RCSessionJoinRequestPdu'];
  249 + joinSessionPdu.id = this._session_id;
  250 + joinSessionPdu.name = this._session_name;
  251 + joinSessionPdu.tag = this._session_tag;
  252 + joinSessionPdu.sessionData = this._adapter_pdu.toArrayBuffer();
  253 + this.sendUniform(joinSessionPdu, true);
  254 +
  255 + var joinChannelPdu = new pdu['RCChannelJoinRequestPdu'];
  256 + joinChannelPdu.initiator = this.mcu.classInfo.nodeId;
  257 + joinChannelPdu.channelId = this._session_id;
  258 + this.send(joinChannelPdu);
309 } 259 }
310 - let normalPdu = pdu.create_normal_pdu(  
311 - appPdu.type,  
312 - this._classInfo.nodeId,  
313 - this._classInfo.classId,  
314 - this._session_id,  
315 - this._channel_id,  
316 - true,  
317 - true,  
318 - PduConsts.DP_TOP,  
319 - this._classInfo.topNodeID,  
320 - PduConsts.SEG_ONCE  
321 - );  
322 - normalPdu.data = appPdu.toArrayBuffer();  
323 - // Mcu发送  
324 - this.mcu.send(normalPdu);  
325 - }  
326 -  
327 - // 发送当前APE(session uniform包)  
328 - sendUniform(appPdu, top) {  
329 - loger.log('Ape发送数据UNIFORM PDU');  
330 - console.log(appPdu);  
331 - //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);  
332 - if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){  
333 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);  
334 - return; 260 +
  261 + // 依赖的录制回放创建完毕 - 发起Ape加入
  262 + _joinRecordPlaybackSuccessHandler(_data) {
  263 + loger.log('录制回放->Ape已经创建完毕->',
  264 + 'SessionId',
  265 + this._session_id,
  266 + 'SessionName',
  267 + this._session_name,
  268 + 'SessionTag',
  269 + this._session_tag);
335 } 270 }
336 271
337 - let uniformPdu = pdu.create_uniform_pdu(  
338 - appPdu.type,  
339 - this._classInfo.nodeId,  
340 - this._classInfo.classId,  
341 - this._session_id,  
342 - top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,  
343 - true,  
344 - PduConsts.DP_TOP,  
345 - top ? this._classInfo.topNodeID : (appPdu.peer || 0),  
346 - PduConsts.SEG_ONCE  
347 - );  
348 - uniformPdu.data = appPdu.toArrayBuffer();  
349 - // Mcu发送  
350 - this.mcu.send(uniformPdu);  
351 - }  
352 -  
353 - sendChatUniform(appPdu, top) {  
354 - loger.log('Ape发送数据UNIFORM PDU');  
355 - console.log(appPdu);  
356 - //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);  
357 - if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){  
358 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);  
359 - return; 272 + // 注册Key对象
  273 + registerKey(id, name, tag, user_data) {
  274 + let adapterItemPdu = new pdu['RCAdapterItemPdu'];
  275 + adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_KEY;
  276 +
  277 + // pack register key pdus
  278 + let registerKeyPdu = new pdu['RCRegistryRegisterKeyPdu'];
  279 + registerKeyPdu.id = id;
  280 + registerKeyPdu.name = name;
  281 + registerKeyPdu.tag = tag;
  282 + if (user_data.length) {
  283 + registerKeyPdu.userData = user_data;
  284 + }
  285 +
  286 + adapterItemPdu.itemData = registerKeyPdu.toArrayBuffer();
  287 + this._adapter_pdu.item.push(adapterItemPdu);
360 } 288 }
361 289
362 - let uniformPdu = pdu.create_uniform_pdu(  
363 - appPdu.type,  
364 - this._classInfo.nodeId,  
365 - this._classInfo.classId,  
366 - this._session_id,  
367 - top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,  
368 - true,  
369 - PduConsts.DP_TOP,  
370 - 0,//flash中这个值设置为0  
371 - PduConsts.SEG_ONCE  
372 - );  
373 - uniformPdu.data = appPdu.toArrayBuffer();  
374 - // Mcu发送  
375 - this.mcu.send(uniformPdu);  
376 - } 290 + // 注册Object对象 等同于flash中的 RCRegistryOperator
  291 + registerObj(type, id, name, tag, owner, user_data) {
  292 + let adapterItemPdu = new pdu['RCAdapterItemPdu'];
  293 + adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_OBJ;
  294 +
  295 + let registerObjPdu = new pdu['RCRegistryRegisterObjPdu'];
  296 + registerObjPdu.type = type;
  297 + registerObjPdu.objId = id;
  298 + registerObjPdu.name = name;
  299 + registerObjPdu.tag = tag;
  300 + if (owner) {
  301 + registerObjPdu.owner = owner;
  302 + }
  303 + if (user_data.length) {
  304 + registerObjPdu.userData = user_data;
  305 + }
  306 +
  307 + adapterItemPdu.itemData = registerObjPdu.toArrayBuffer();
  308 + this._adapter_pdu.item.push(adapterItemPdu);
  309 + }
  310 +
  311 + send(appPdu) {
  312 + loger.log('Ape发送数据NORMAL PDU');
  313 + //console.log(appPdu);
  314 + //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
  315 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  316 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
  317 + return;
  318 + }
  319 + let normalPdu = pdu.create_normal_pdu(
  320 + appPdu.type,
  321 + this._classInfo.nodeId,
  322 + this._classInfo.classId,
  323 + this._session_id,
  324 + this._channel_id,
  325 + true,
  326 + true,
  327 + PduConsts.DP_TOP,
  328 + this._classInfo.topNodeID,
  329 + PduConsts.SEG_ONCE
  330 + );
  331 + normalPdu.data = appPdu.toArrayBuffer();
  332 + // Mcu发送
  333 + this.mcu.send(normalPdu);
  334 + }
  335 +
  336 + // 发送当前APE(session uniform包)
  337 + sendUniform(appPdu, top) {
  338 + loger.log('Ape发送数据UNIFORM PDU');
  339 + //console.log(appPdu);
  340 + //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
  341 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  342 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
  343 + return;
  344 + }
  345 +
  346 + let uniformPdu = pdu.create_uniform_pdu(
  347 + appPdu.type,
  348 + this._classInfo.nodeId,
  349 + this._classInfo.classId,
  350 + this._session_id,
  351 + top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,
  352 + true,
  353 + PduConsts.DP_TOP,
  354 + top ? this._classInfo.topNodeID : (appPdu.peer || 0),
  355 + PduConsts.SEG_ONCE
  356 + );
  357 + uniformPdu.data = appPdu.toArrayBuffer();
  358 + // Mcu发送
  359 + this.mcu.send(uniformPdu);
  360 + }
  361 +
  362 + sendChatUniform(appPdu, top) {
  363 + loger.log('Ape发送数据UNIFORM PDU');
  364 + //console.log(appPdu);
  365 + //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
  366 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  367 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
  368 + return;
  369 + }
  370 +
  371 + let uniformPdu = pdu.create_uniform_pdu(
  372 + appPdu.type,
  373 + this._classInfo.nodeId,
  374 + this._classInfo.classId,
  375 + this._session_id,
  376 + top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,
  377 + true,
  378 + PduConsts.DP_TOP,
  379 + 0,//flash中这个值设置为0
  380 + PduConsts.SEG_ONCE
  381 + );
  382 + uniformPdu.data = appPdu.toArrayBuffer();
  383 + // Mcu发送
  384 + this.mcu.send(uniformPdu);
  385 + }
377 } 386 }
378 387
@@ -11,7 +11,7 @@ export default function ApeConsts(id) { @@ -11,7 +11,7 @@ export default function ApeConsts(id) {
11 ApeConsts.CLASS_STATUS_WAIT= 0;//课堂还未开始 11 ApeConsts.CLASS_STATUS_WAIT= 0;//课堂还未开始
12 ApeConsts.CLASS_STATUS_STARTED= 1;//直播中 12 ApeConsts.CLASS_STATUS_STARTED= 1;//直播中
13 ApeConsts.CLASS_STATUS_PAUSE= 2;//暂停 13 ApeConsts.CLASS_STATUS_PAUSE= 2;//暂停
14 -ApeConsts.CLASS_STATUS_CLOSE= 3;//结束//这个是点击结束会议,把所有人踢出课堂,然后把状态值还原为0************* 14 +ApeConsts.CLASS_STATUS_CLOSE= 3;//结束//这个是点击结束课堂,把所有人踢出课堂,然后把状态值还原为0*************
15 ApeConsts.CLASS_STATUS_UPTATE= 4;//更新课堂状态信息 15 ApeConsts.CLASS_STATUS_UPTATE= 4;//更新课堂状态信息
16 16
17 ApeConsts.CLASS_WAIT_START = "class.wait.start";//课堂还未开始 17 ApeConsts.CLASS_WAIT_START = "class.wait.start";//课堂还未开始
@@ -22,7 +22,7 @@ ApeConsts.CLASS_PAUSING = "class.update";//更新当前的状态信息 @@ -22,7 +22,7 @@ ApeConsts.CLASS_PAUSING = "class.update";//更新当前的状态信息
22 22
23 23
24 //课堂控制 24 //课堂控制
25 -ApeConsts.CLASS_ACTION_CLOSE_ALL=1;//所有人关闭会议 25 +ApeConsts.CLASS_ACTION_CLOSE_ALL=1;//所有人关闭课堂
26 26
27 //课堂类型 27 //课堂类型
28 ApeConsts.CLASS_TYPE_INTERACT= 1; // 互动课堂,通过MS转发音视频,不能进行H5观看 28 ApeConsts.CLASS_TYPE_INTERACT= 1; // 互动课堂,通过MS转发音视频,不能进行H5观看
@@ -35,7 +35,7 @@ public static const NR_GUEST:uint = 0; // 客人 @@ -35,7 +35,7 @@ public static const NR_GUEST:uint = 0; // 客人
35 public static const NR_NORMAL:uint = 1; // 普通与会者 35 public static const NR_NORMAL:uint = 1; // 普通与会者
36 public static const NR_ADMIN:uint = 2; // 管理员 36 public static const NR_ADMIN:uint = 2; // 管理员
37 public static const NR_MASTER:uint = 4; // 主持人 37 public static const NR_MASTER:uint = 4; // 主持人
38 -public static const NR_SLAVE:uint = 8; // 主讲人 38 +public static const NR_PRESENTER:uint = 8; // 主讲人
39 public static const NR_ASSISTANT:uint = 16; // 助教 39 public static const NR_ASSISTANT:uint = 16; // 助教
40 public static const NR_INVISIBLE:uint = 32; // 隐身用户 40 public static const NR_INVISIBLE:uint = 32; // 隐身用户
41 */ 41 */
@@ -45,8 +45,8 @@ public static const NR_INVISIBLE:uint = 32; // 隐身用户 @@ -45,8 +45,8 @@ public static const NR_INVISIBLE:uint = 32; // 隐身用户
45 //ApeConsts.NR_GUEST = 0; // 客人 45 //ApeConsts.NR_GUEST = 0; // 客人
46 ApeConsts.NR_NORMAL = 1;// 普通与会者 46 ApeConsts.NR_NORMAL = 1;// 普通与会者
47 ApeConsts.NR_ADMIN = 2;// 管理员 47 ApeConsts.NR_ADMIN = 2;// 管理员
48 -ApeConsts.NR_MASTER = 4; // 主持人  
49 -ApeConsts.NR_SLAVE = 8; // 主讲人 48 +ApeConsts.NR_HOST = 4; // 主持人
  49 +ApeConsts.NR_PRESENTER = 8; // 主讲人
50 ApeConsts.NR_ASSISTANT = 16; // 助教 50 ApeConsts.NR_ASSISTANT = 16; // 助教
51 ApeConsts.NR_INVISIBLE = 32; // 隐身用户 51 ApeConsts.NR_INVISIBLE = 32; // 隐身用户
52 52
@@ -58,6 +58,23 @@ ApeConsts.normal="normal";//(普通角色/学生) @@ -58,6 +58,23 @@ ApeConsts.normal="normal";//(普通角色/学生)
58 ApeConsts.record="record";//(暂时没用. 58 ApeConsts.record="record";//(暂时没用.
59 ApeConsts.invisible="invisible";//隐身用户 59 ApeConsts.invisible="invisible";//隐身用户
60 60
  61 +//下面做身份的数字和字符串对应关系
  62 +ApeConsts.userTypes={};
  63 +ApeConsts.userTypes[ApeConsts.NR_NORMAL]=ApeConsts.normal;
  64 +ApeConsts.userTypes[ApeConsts.NR_ADMIN]=ApeConsts.record;
  65 +ApeConsts.userTypes[ApeConsts.NR_HOST]=ApeConsts.host;
  66 +ApeConsts.userTypes[ApeConsts.NR_PRESENTER]=ApeConsts.presenter;
  67 +ApeConsts.userTypes[ApeConsts.NR_ASSISTANT]=ApeConsts.assistant;
  68 +ApeConsts.userTypes[ApeConsts.NR_INVISIBLE]=ApeConsts.invisible;
  69 +
  70 +ApeConsts.userTypesToId={};
  71 +ApeConsts.userTypesToId[ApeConsts.normal]=ApeConsts.NR_NORMAL;
  72 +ApeConsts.userTypesToId[ApeConsts.record]=ApeConsts.NR_ADMIN;
  73 +ApeConsts.userTypesToId[ApeConsts.host]=ApeConsts.NR_HOST;
  74 +ApeConsts.userTypesToId[ApeConsts.presenter]=ApeConsts.NR_PRESENTER;
  75 +ApeConsts.userTypesToId[ApeConsts.assistant]=ApeConsts.NR_ASSISTANT;
  76 +ApeConsts.userTypesToId[ApeConsts.invisible]=ApeConsts.NR_INVISIBLE;
  77 +
61 ////最新定义的角色身份 20170220 78 ////最新定义的角色身份 20170220
62 //ApeConsts.USER_TYPE_HOST=1;//(主持人/老师) 79 //ApeConsts.USER_TYPE_HOST=1;//(主持人/老师)
63 //ApeConsts.USER_TYPE_ASSISTANT=2;//(助教) 80 //ApeConsts.USER_TYPE_ASSISTANT=2;//(助教)