李勇

Merge branch 'mcuClientBranch'

要显示太多修改。

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

此 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,29 +22,23 @@ import GlobalConfig from 'GlobalConfig'; @@ -19,29 +22,23 @@ 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 {
@@ -61,27 +58,38 @@ export default class MessageEntrance extends Emiter { @@ -61,27 +58,38 @@ export default class MessageEntrance extends Emiter {
61 _sass = Sass; 58 _sass = Sass;
62 _sass.on('*', (type, data) => this._emit(type, data)); 59 _sass.on('*', (type, data) => this._emit(type, data));
63 _sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5) 60 _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));//保存会议录制信息 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));//保存课堂录制信息
69 _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功 67 _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功
70 68
  69 + //ServerCheck ip
  70 + _serverCheck = ServerCheck;
  71 + _serverCheck.on(_serverCheck.SEVER_CHECK_BEST_IP_SUCCESS, this._serverCheckBestIpSuccessHandler.bind(this));//ip选点,获取最佳ip完成
  72 +
  73 +
71 // 底层MCU消息层 74 // 底层MCU消息层
72 _mcu = Mcu; 75 _mcu = Mcu;
73 _mcu.on('*', (type, data) => this._emit(type, data)); 76 _mcu.on('*', (type, data) => this._emit(type, data));
74 - _mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this));//加入MCU会议完成 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));//加入录制回放完成
75 83
76 84
77 // 注册所有应用Ape 85 // 注册所有应用Ape
78 _confer_ape = new ConferApe(); 86 _confer_ape = new ConferApe();
79 _confer_ape.on('*', (type, data) => this._emit(type, data)); 87 _confer_ape.on('*', (type, data) => this._emit(type, data));
80 _confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件 88 _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));//会议开始录制 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));//课堂开始录制
85 93
86 94
87 _chat_ape = new ChatApe(); 95 _chat_ape = new ChatApe();
@@ -89,11 +97,12 @@ export default class MessageEntrance extends Emiter { @@ -89,11 +97,12 @@ export default class MessageEntrance extends Emiter {
89 97
90 _video_ape = new VideoApe(); 98 _video_ape = new VideoApe();
91 _video_ape.on('*', (type, data) => this._emit(type, data)); 99 _video_ape.on('*', (type, data) => this._emit(type, data));
92 - //_video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this)); 100 + _video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this));//这个监听事件不能删除,需要通知课堂模块,检查channel占用
93 101
94 - _audio_ape= new AudioApe(); 102 +
  103 + _audio_ape = new AudioApe();
95 _audio_ape.on('*', (type, data) => this._emit(type, data)); 104 _audio_ape.on('*', (type, data) => this._emit(type, data));
96 - //_audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this)); 105 + _audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this));//这个监听事件不能删除,需要通知课堂模块,检查channel占用
97 106
98 _whiteboard_ape = new WhiteBoardApe(); 107 _whiteboard_ape = new WhiteBoardApe();
99 _whiteboard_ape.on('*', (type, data) => this._emit(type, data)); 108 _whiteboard_ape.on('*', (type, data) => this._emit(type, data));
@@ -105,8 +114,6 @@ export default class MessageEntrance extends Emiter { @@ -105,8 +114,6 @@ export default class MessageEntrance extends Emiter {
105 _doc_ape.on(MessageTypes.DOC_DELETE, this.docDeleteHandler.bind(this)); 114 _doc_ape.on(MessageTypes.DOC_DELETE, this.docDeleteHandler.bind(this));
106 _doc_ape.on(DocApe.DOC_JOIN_CHANNEL_SUCCESS, this.docJoinChannelSuccess.bind(this)); 115 _doc_ape.on(DocApe.DOC_JOIN_CHANNEL_SUCCESS, this.docJoinChannelSuccess.bind(this));
107 116
108 -  
109 -  
110 //公开外部调用的方法 117 //公开外部调用的方法
111 //class 118 //class
112 this.init = this._init.bind(this); 119 this.init = this._init.bind(this);
@@ -119,24 +126,32 @@ export default class MessageEntrance extends Emiter { @@ -119,24 +126,32 @@ export default class MessageEntrance extends Emiter {
119 this.sendPauseClass = this._sendPauseClass.bind(this); 126 this.sendPauseClass = this._sendPauseClass.bind(this);
120 this.sendCloseClass = this._sendCloseClass.bind(this); 127 this.sendCloseClass = this._sendCloseClass.bind(this);
121 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);
122 135
123 //chatApe 136 //chatApe
124 this.sendChatMsg = this._sendChatMsg.bind(this); 137 this.sendChatMsg = this._sendChatMsg.bind(this);
125 138
126 //videoApe 139 //videoApe
127 - this.getVideoPlayPath = this._getVideoPlayPath.bind(this); 140 + //this.getVideoPlayPath = this._getVideoPlayPath.bind(this);
128 this.getVideoPublishPath = this._getVideoPublishPath.bind(this); 141 this.getVideoPublishPath = this._getVideoPublishPath.bind(this);
  142 + this.getVideoAllChannelInfo = this._getVideoAllChannelInfo.bind(this);
129 this.publishVideo = this._publishVideo.bind(this); 143 this.publishVideo = this._publishVideo.bind(this);
130 this.stopPublishVideo = this._stopPublishVideo.bind(this); 144 this.stopPublishVideo = this._stopPublishVideo.bind(this);
131 - this.sendVideoBroadcastMsg=this._sendVideoBroadcastMsg.bind(this); 145 + this.sendVideoBroadcastMsg = this._sendVideoBroadcastMsg.bind(this);
132 146
133 147
134 //audioApe 148 //audioApe
135 - this.getAudioPlayPath = this._getPlayAudioPath.bind(this); 149 + //this.getAudioPlayPath = this._getPlayAudioPath.bind(this);
136 this.getAudioPublishPath = this._getPublishAudioPath.bind(this); 150 this.getAudioPublishPath = this._getPublishAudioPath.bind(this);
  151 + this.getAudioAllChannelInfo = this._getAudioAllChannelInfo.bind(this);
137 this.publishAudio = this._publishAudio.bind(this); 152 this.publishAudio = this._publishAudio.bind(this);
138 this.stopPublishAudio = this._stopPublishAudio.bind(this); 153 this.stopPublishAudio = this._stopPublishAudio.bind(this);
139 - this.sendAudioBroadcastMsg=this.sendAudioCommandMsg.bind(this); 154 + this.sendAudioBroadcastMsg = this.sendAudioCommandMsg.bind(this);
140 155
141 //whiteBoradApe 156 //whiteBoradApe
142 this.sendInsertAnnotaion = this._sendInsertAnnotaion.bind(this); 157 this.sendInsertAnnotaion = this._sendInsertAnnotaion.bind(this);
@@ -146,16 +161,19 @@ export default class MessageEntrance extends Emiter { @@ -146,16 +161,19 @@ export default class MessageEntrance extends Emiter {
146 this.sendGotoPrev = this._sendGotoPrev.bind(this); 161 this.sendGotoPrev = this._sendGotoPrev.bind(this);
147 162
148 //DocApe 163 //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 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
153 //this.sendDocumentDeleteAll= this._documentDeleteAll;//删除所有文档 169 //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 - } 170 + this.sendDocumentCommand = this._sendDocumentCommand.bind(this);
  171 + //操作文档(翻页、缩放、滚动...)
  172 + this.getDocImageFullPath = this._getDocImageFullPath.bind(this);
  173 + //获取文档图片的完整路径
  174 + this.getDocPDFFullPath = this._getDocPDFFullPath.bind(this);//获取文档的完整路径
158 175
  176 + }
159 177
160 //mcu异常监听 178 //mcu异常监听
161 _mcuErrorHandler(_data, _option) { 179 _mcuErrorHandler(_data, _option) {
@@ -163,9 +181,9 @@ export default class MessageEntrance extends Emiter { @@ -163,9 +181,9 @@ export default class MessageEntrance extends Emiter {
163 let errorMessage = {"code": _data, "reson": MessageTypes.ErrorReson[_data] + " " + option}; 181 let errorMessage = {"code": _data, "reson": MessageTypes.ErrorReson[_data] + " " + option};
164 loger.error("MCU_ERROR", errorMessage); 182 loger.error("MCU_ERROR", errorMessage);
165 183
166 - this._emit(MessageTypes.ERROR_EVENT,errorMessage); 184 + this._emit(MessageTypes.ERROR_EVENT, errorMessage);
167 185
168 -/* if (_mcuErrorCallBackFun) { 186 + /* if (_mcuErrorCallBackFun) {
169 _mcuErrorCallBackFun(errorMessage); 187 _mcuErrorCallBackFun(errorMessage);
170 }*/ 188 }*/
171 } 189 }
@@ -175,53 +193,55 @@ export default class MessageEntrance extends Emiter { @@ -175,53 +193,55 @@ export default class MessageEntrance extends Emiter {
175 return GlobalConfig.getCurrentStatus(); 193 return GlobalConfig.getCurrentStatus();
176 } 194 }
177 195
178 -//获取会议信息 196 +//获取课堂信息
179 _getClassDetail() { 197 _getClassDetail() {
180 return GlobalConfig.getClassDetail(); 198 return GlobalConfig.getClassDetail();
181 } 199 }
182 200
183 - //获取当前会议的状态信息  
184 - _getClassStatusInfo(){ 201 + //获取当前课堂的状态信息
  202 + _getClassStatusInfo() {
185 return GlobalConfig.classStatusInfo; 203 return GlobalConfig.classStatusInfo;
186 } 204 }
187 - //关闭会议,所有人都退出 205 +
  206 + //关闭课堂,所有人都退出
188 _doClassClose(_param) { 207 _doClassClose(_param) {
189 this._leaveClass(); 208 this._leaveClass();
190 } 209 }
191 210
192 - //离开会议,断开连接 211 + //离开课堂,断开连接
193 _doClassExit() { 212 _doClassExit() {
194 this._leaveClass(); 213 this._leaveClass();
195 } 214 }
196 215
197 - //当前的会议状态信息发生改变,需要保存会议状态到Sass 216 + //当前的课堂状态信息发生改变,需要保存课堂状态到Sass
198 _onClassStatusInfoChange(_param) { 217 _onClassStatusInfoChange(_param) {
199 //如果MCU连接已经断开,不发送 218 //如果MCU连接已经断开,不发送
200 - if(GlobalConfig.getCurrentStatus().code!=GlobalConfig.statusCode_2.code){  
201 - loger.warn("不能保存会议状态",GlobalConfig.getCurrentStatus()); 219 + if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {
  220 + loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
202 return; 221 return;
203 } 222 }
204 this._sassSaveClassStatusInfo(); 223 this._sassSaveClassStatusInfo();
205 } 224 }
206 225
207 //如果是第一次点击开始上课,需要创建录制时的文件名 226 //如果是第一次点击开始上课,需要创建录制时的文件名
208 - _onClassRecordStart(_param){  
209 - if(GlobalConfig.getCurrentStatus().code!=GlobalConfig.statusCode_2.code){  
210 - loger.warn("不能保存会议状态",GlobalConfig.getCurrentStatus()); 227 + _onClassRecordStart(_param) {
  228 + if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {
  229 + loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
211 return; 230 return;
212 } 231 }
213 - if(_sass){ 232 + if (_sass) {
214 _sass.saveClassRecordContrlInfo(_param); 233 _sass.saveClassRecordContrlInfo(_param);
215 } 234 }
216 } 235 }
217 236
218 237
219 //有人员离开 238 //有人员离开
220 - _onClassDeleteRoster(_data){ 239 + _onClassDeleteRoster(_data) {
  240 +
  241 + //在conferApe中做处理,这里不需要再处理
221 //{"nodeId":nodeId} 242 //{"nodeId":nodeId}
222 //当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel; 243 //当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;
223 - //只有自己是主持人的时候出才处理下面的事情  
224 - if(_data!=null&&_data.nodeId!=null&&GlobalConfig.isHost){ 244 + /* if(_data!=null&&_data.nodeId!=null){
225 loger.log("有人员离开,检查一下离开的人员是否关闭推流"); 245 loger.log("有人员离开,检查一下离开的人员是否关闭推流");
226 if(_video_ape){ 246 if(_video_ape){
227 _video_ape.stopPublishVideo(_data); 247 _video_ape.stopPublishVideo(_data);
@@ -229,21 +249,26 @@ export default class MessageEntrance extends Emiter { @@ -229,21 +249,26 @@ export default class MessageEntrance extends Emiter {
229 if(_audio_ape){ 249 if(_audio_ape){
230 _audio_ape.stopPublishAudio(_data); 250 _audio_ape.stopPublishAudio(_data);
231 } 251 }
232 - } 252 + }*/
233 } 253 }
234 254
235 - //当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel 255 + //当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
236 //的占用状态导致,对于这种情况,需要释放掉 256 //的占用状态导致,对于这种情况,需要释放掉
237 - _onClassNonentityRoster(_param){  
238 - if(_param==null||_param.nodeId==null){ 257 + _onClassNonentityRoster(_param) {
  258 + if(GlobalConfig.isRecordPlayBack){
  259 + loger.warn("录制回放中,不处理")
  260 + return;
  261 + }
  262 +
  263 + if (_param == null || _param.nodeId == null) {
239 loger.warn("onClassNonentityRoster.参数错误") 264 loger.warn("onClassNonentityRoster.参数错误")
240 return; 265 return;
241 } 266 }
242 - let data={"nodeId":_param.nodeId};  
243 - if(_video_ape){ 267 + let data = {"nodeId": _param.nodeId};
  268 + if (_video_ape) {
244 _video_ape.stopPublishVideo(data); 269 _video_ape.stopPublishVideo(data);
245 } 270 }
246 - if(_audio_ape){ 271 + if (_audio_ape) {
247 _audio_ape.stopPublishAudio(data); 272 _audio_ape.stopPublishAudio(data);
248 } 273 }
249 } 274 }
@@ -268,11 +293,17 @@ export default class MessageEntrance extends Emiter { @@ -268,11 +293,17 @@ export default class MessageEntrance extends Emiter {
268 loger.log('init', _param); 293 loger.log('init', _param);
269 294
270 //保存参数 295 //保存参数
  296 + GlobalConfig.isRecordPlayBack=false;//设置为非录制回放状态
271 GlobalConfig.classId = parseInt(_param.classId); 297 GlobalConfig.classId = parseInt(_param.classId);
272 GlobalConfig.portal = _param.portal; 298 GlobalConfig.portal = _param.portal;
273 GlobalConfig.userRole = _param.userRole || ApeConsts.normal; 299 GlobalConfig.userRole = _param.userRole || ApeConsts.normal;
274 GlobalConfig.userId = _param.userId || "0"; 300 GlobalConfig.userId = _param.userId || "0";
275 - GlobalConfig.userName=_param.userName || ""; 301 + GlobalConfig.userName = _param.userName || "";
  302 +
  303 + //最长允许录制的时间
  304 + if(_param.allowRecordMaxTime){
  305 + GlobalConfig.allowRecordMaxTime=parseInt(_param.allowRecordMaxTime);
  306 + }
276 307
277 //获取课堂校验信息 308 //获取课堂校验信息
278 if (_sass) { 309 if (_sass) {
@@ -280,34 +311,45 @@ export default class MessageEntrance extends Emiter { @@ -280,34 +311,45 @@ export default class MessageEntrance extends Emiter {
280 } 311 }
281 } 312 }
282 313
283 - //外部请求加入会议 314 + //外部请求加入课堂
284 _joinClass(_param) { 315 _joinClass(_param) {
285 //_joinClassSuccessCallBackFun = _onSuccess; 316 //_joinClassSuccessCallBackFun = _onSuccess;
286 //{"userName":"名字","password":""} 317 //{"userName":"名字","password":""}
287 if (_param == null || EngineUtils.isEmptyObject(_param)) { 318 if (_param == null || EngineUtils.isEmptyObject(_param)) {
288 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM); 319 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
289 - loger.log('不能进入会议,传递的参数不对.', _param); 320 + loger.log('不能进入课堂,传递的参数不对.', _param);
290 return; 321 return;
291 } 322 }
292 //判断userName 323 //判断userName
293 if (_param.userName == null || _param.userName == "") { 324 if (_param.userName == null || _param.userName == "") {
294 - loger.log('不能进入会议,传递的参数不对.名字不能为空'); 325 + loger.log('不能进入课堂,传递的参数不对.名字不能为空');
295 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM); 326 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
296 return; 327 return;
297 } 328 }
298 329
299 - if(GlobalConfig.userName==null||GlobalConfig.userName==""){ 330 + if (GlobalConfig.userName == null || GlobalConfig.userName == "") {
300 GlobalConfig.userName = _param.userName; 331 GlobalConfig.userName = _param.userName;
301 } 332 }
  333 + GlobalConfig.autoLogin=_param.autoLogin||"";
302 GlobalConfig.password = _param.password || ""; 334 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 - //开始校验 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 + //不能自动登录,开始校验
307 if (_sass) { 348 if (_sass) {
308 _sass.passwordAndMd5Checking(GlobalConfig.getClassInfo()); 349 _sass.passwordAndMd5Checking(GlobalConfig.getClassInfo());
309 } 350 }
310 } 351 }
  352 + }
311 353
312 // 用classId向SASS平台获取入会验证信息成功 354 // 用classId向SASS平台获取入会验证信息成功
313 _sassInitSuccessHandler(_data) { 355 _sassInitSuccessHandler(_data) {
@@ -323,7 +365,7 @@ export default class MessageEntrance extends Emiter { @@ -323,7 +365,7 @@ export default class MessageEntrance extends Emiter {
323 365
324 loger.log('SASS平台获取入会验证信息成功.'); 366 loger.log('SASS平台获取入会验证信息成功.');
325 367
326 - //设置当前的会议状态 368 + //设置当前的课堂状态
327 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_1); 369 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_1);
328 //返回给客户端初始化成功的数据 370 //返回给客户端初始化成功的数据
329 let initSuccessCallBackData = {}; 371 let initSuccessCallBackData = {};
@@ -331,21 +373,17 @@ export default class MessageEntrance extends Emiter { @@ -331,21 +373,17 @@ export default class MessageEntrance extends Emiter {
331 initSuccessCallBackData.classId = GlobalConfig.classId; 373 initSuccessCallBackData.classId = GlobalConfig.classId;
332 initSuccessCallBackData.userRole = GlobalConfig.userRole; 374 initSuccessCallBackData.userRole = GlobalConfig.userRole;
333 initSuccessCallBackData.userId = GlobalConfig.userId; 375 initSuccessCallBackData.userId = GlobalConfig.userId;
  376 + initSuccessCallBackData.userName = GlobalConfig.userName;
334 initSuccessCallBackData.classType = GlobalConfig.classType; 377 initSuccessCallBackData.classType = GlobalConfig.classType;
335 378
336 //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的 379 //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
337 - if (GlobalConfig.userRole== ApeConsts.host) {  
338 - initSuccessCallBackData.passwordRequired =true; 380 + if (GlobalConfig.userRole == ApeConsts.host) {
  381 + initSuccessCallBackData.passwordRequired = true;
339 } else { 382 } else {
340 initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired; 383 initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
341 } 384 }
342 385
343 - this._emit(MessageTypes.CLASS_INIT_SUCCESS,initSuccessCallBackData);  
344 -  
345 -/* if (_initSuccessCallBackFun) {  
346 - _initSuccessCallBackFun(initSuccessCallBackData);  
347 - }*/  
348 - 386 + this._emit(MessageTypes.CLASS_INIT_SUCCESS, initSuccessCallBackData);
349 } 387 }
350 388
351 // 通过SASS平台验证(密码和MD5) 389 // 通过SASS平台验证(密码和MD5)
@@ -361,117 +399,24 @@ export default class MessageEntrance extends Emiter { @@ -361,117 +399,24 @@ export default class MessageEntrance extends Emiter {
361 mcu 字符串 Mcu列表 399 mcu 字符串 Mcu列表
362 rs 字符串 Rs列表 400 rs 字符串 Rs列表
363 doc 字符串 Doc列表*/ 401 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 - //获取会议最完整的数据 402 + //获取课堂最完整的数据
425 if (_sass) { 403 if (_sass) {
426 _sass.getClassParam(); 404 _sass.getClassParam();
427 } 405 }
428 } 406 }
429 407
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 408 + //获取课堂所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do
466 _sassGetClassParamSuccessHandler(_data) { 409 _sassGetClassParamSuccessHandler(_data) {
467 //console.log(GlobalConfig.classStatusInfo) 410 //console.log(GlobalConfig.classStatusInfo)
468 - loger.log('获取课堂会议的完整信息完成.'); 411 + loger.log('获取课堂课堂的完整信息完成.');
469 // console.log(_data); 412 // console.log(_data);
470 - //包含整个会议最全的信息,储存数据 413 + //包含整个课堂最全的信息,储存数据
471 if (_data) { 414 if (_data) {
  415 + GlobalConfig.mcuDelay = _data.mcuDelay || 60;//mcu消息延迟,用于文档模块
472 GlobalConfig.className = _data.meetingName || ""; 416 GlobalConfig.className = _data.meetingName || "";
473 GlobalConfig.classBeginTime = _data.beginTime || ""; 417 GlobalConfig.classBeginTime = _data.beginTime || "";
474 GlobalConfig.classEndTime = _data.endTime || ""; 418 GlobalConfig.classEndTime = _data.endTime || "";
  419 + GlobalConfig.userIp = _data.userIp || "";
475 420
476 GlobalConfig.maxVideoChannels = _data.maxVideoChannels; 421 GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
477 GlobalConfig.maxAudioChannels = _data.maxAudioChannels; 422 GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
@@ -486,142 +431,177 @@ export default class MessageEntrance extends Emiter { @@ -486,142 +431,177 @@ export default class MessageEntrance extends Emiter {
486 GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表 431 GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表
487 432
488 433
489 - if (_data.mcuList) { 434 + if (_data.mcuList&&_data.mcuList.length>0) {
490 //MCU地址默认使用第一个 435 //MCU地址默认使用第一个
491 - GlobalConfig.MCUServerIP =_data.mcuList[0].ip||"";  
492 - GlobalConfig.MCUServerPort =_data.mcuList[0].port||""; 436 + GlobalConfig.MCUServerIP = _data.mcuList[0].ip || "";
  437 + GlobalConfig.MCUServerPort = _data.mcuList[0].port || "";
493 } 438 }
494 439
495 - //视频推流播流地址  
496 - if (_data.msList) { 440 + //上课中视频推流播流地址
  441 + if (_data.msList&&_data.msList.length>0) {
497 //MS地址默认使用第一个 442 //MS地址默认使用第一个
498 - GlobalConfig.MSServerIP =_data.msList[0].ip||"";  
499 - GlobalConfig.MSServerPort =_data.msList[0].port||""; 443 + GlobalConfig.MSServerIP = _data.msList[0].ip || "";
  444 + GlobalConfig.MSServerPort = _data.msList[0].port || "";
500 } 445 }
501 446
502 - //m3u8播流地址  
503 - if(_data.rsList){ 447 + //录制回放时m3u8播流地址
  448 + if (_data.rsList&&_data.rsList.length>0) {
504 //RS地址默认使用第一个 449 //RS地址默认使用第一个
505 - GlobalConfig.RSServerIP =_data.rsList[0].ip||"";  
506 - GlobalConfig.RSServerPort =_data.rsList[0].port||""; 450 + GlobalConfig.RSServerIP = _data.rsList[0].ip || "";
  451 + GlobalConfig.RSServerPort = _data.rsList[0].port || "";
507 } 452 }
508 453
509 //文档地址 454 //文档地址
510 - if(_data.docList){ 455 + if (_data.docList&&_data.docList.length>0) {
511 //doc地址默认使用第一个 456 //doc地址默认使用第一个
512 - GlobalConfig.DOCServerIP =_data.docList[0].ip||"";  
513 - GlobalConfig.DOCServerPort =_data.docList[0].port||""; 457 + GlobalConfig.DOCServerIP = _data.docList[0].ip || "";
  458 + GlobalConfig.DOCServerPort = _data.docList[0].port || "";
514 } 459 }
515 460
516 //record 461 //record
517 - if(_data.recordList){ 462 + if (_data.recordList&&_data.recordList.length>0) {
518 //地址默认使用第一个 463 //地址默认使用第一个
519 - GlobalConfig.RecordServerIP =_data.recordList[0].ip||"";  
520 - GlobalConfig.RecordServerPort =_data.recordList[0].port||""; 464 + GlobalConfig.RecordServerIP = _data.recordList[0].ip || "";
  465 + GlobalConfig.RecordServerPort = _data.recordList[0].port || "";
521 } 466 }
522 467
523 } 468 }
524 469
525 if (_data.currentInfo) { 470 if (_data.currentInfo) {
526 - //根据从Sass获取的数据信息,同步最后一次保存的会议状态信息  
527 - loger.log("同步最后一次保存过的会议状态信息"); 471 + //根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息
  472 + loger.log("本地同步最后一次保存过的课堂状态信息");
  473 + try {
  474 + GlobalConfig.setClassStatusInfo(JSON.parse(_data.currentInfo));
  475 + }catch (err){
528 GlobalConfig.setClassStatusInfo(_data.currentInfo); 476 GlobalConfig.setClassStatusInfo(_data.currentInfo);
529 - console.log(GlobalConfig.classStatusInfo); 477 + }
  478 + loger.log(GlobalConfig.classStatusInfo);
530 } else { 479 } else {
531 - loger.log("还没有保存过会议状信息"); 480 + loger.log("还没有保存过课堂状信息");
532 } 481 }
533 482
534 - //所有Sass流程完成,开始MCU连接 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选点结束");
535 this._joinMCU(); 509 this._joinMCU();
536 } 510 }
537 511
538 - //保存会议状态信息 512 + //保存课堂状态信息
539 _sassSaveClassStatusInfo() { 513 _sassSaveClassStatusInfo() {
540 if (GlobalConfig.isHost) { 514 if (GlobalConfig.isHost) {
541 - //只有加入会议之后才能保存数据 515 + //只有加入课堂之后才能保存数据
542 if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) { 516 if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
543 //POST 保存数据 517 //POST 保存数据
544 - _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo});//保存会议状态信息 518 + _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo});//保存课堂状态信息
545 } else { 519 } else {
546 - loger.error("不能保存会议数据", GlobalConfig.getCurrentStatus()); 520 + loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());
547 } 521 }
548 } else { 522 } else {
549 - loger.log("没有保存会议状态信息的权限 isHost", GlobalConfig.isHost); 523 + loger.log("没有保存课堂状态信息的权限 isHost", GlobalConfig.isHost);
550 } 524 }
551 } 525 }
552 526
553 //保存会态信息成功 527 //保存会态信息成功
554 _sassSaveClassStatusInfoSuccessHandler(_data) { 528 _sassSaveClassStatusInfoSuccessHandler(_data) {
555 - loger.log('保存会议状态信息成功.');  
556 - console.log(_data); 529 + loger.log('保存课堂状态信息成功.');
  530 + loger.log(_data);
557 } 531 }
558 - _sassSaveClassRecordInfoSuccessHandler(_data){  
559 - loger.log('保存会议录制信息成功.');  
560 - console.log(_data); 532 +
  533 + _sassSaveClassRecordInfoSuccessHandler(_data) {
  534 + loger.log('保存课堂录制信息成功.');
  535 + loger.log(_data);
561 } 536 }
562 537
563 //Sass校验流程结束之后,开始加入MCU 538 //Sass校验流程结束之后,开始加入MCU
564 _joinMCU() { 539 _joinMCU() {
565 - loger.log('加入底层MCU会议.'); 540 + loger.log('加入底层MCU课堂.');
566 if (_mcu) { 541 if (_mcu) {
567 _mcu.joinMCU(GlobalConfig.getClassInfo()); 542 _mcu.joinMCU(GlobalConfig.getClassInfo());
568 } 543 }
569 } 544 }
570 545
571 - // MCU 会议成功 546 + // MCU 课堂成功
572 _mcuJoinMCUClassSuccessHandler(_data) { 547 _mcuJoinMCUClassSuccessHandler(_data) {
573 - loger.log('MCU 会议成功.'); 548 + loger.log('MCU 课堂成功.');
574 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2); 549 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
575 550
576 //返回给客户端初始化成功的数据 551 //返回给客户端初始化成功的数据
577 - let initSuccessCallBackData = {}; 552 + let joinClassSuccessCallBackData = {};
578 553
579 - initSuccessCallBackData.DOCServerIP =GlobalConfig.DOCServerIP;  
580 - initSuccessCallBackData.DOCServerPort =GlobalConfig.DOCServerPort; 554 + joinClassSuccessCallBackData.isRecordPlayBack=GlobalConfig.isRecordPlayBack;
581 555
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; 556 + joinClassSuccessCallBackData.DOCServerIP = GlobalConfig.DOCServerIP;
  557 + joinClassSuccessCallBackData.DOCServerPort = GlobalConfig.DOCServerPort;
603 558
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); 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;
612 566
613 - //加入会议成功,广播消息  
614 - this._emit(MessageTypes.CLASS_JOIN_SUCCESS,initSuccessCallBackData);  
615 -  
616 -/* //返回给客户数据  
617 - if (_joinClassSuccessCallBackFun) {  
618 - _joinClassSuccessCallBackFun(initSuccessCallBackData);  
619 - }*/ 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);
620 } 600 }
621 601
622 //Sass删除文档数据 602 //Sass删除文档数据
623 _sassDeleteDocument(_param) { 603 _sassDeleteDocument(_param) {
624 - if(!_mcu.connected){ 604 + if (!_mcu.connected) {
625 loger.warn(GlobalConfig.getCurrentStatus()); 605 loger.warn(GlobalConfig.getCurrentStatus());
626 return; 606 return;
627 } 607 }
@@ -653,57 +633,60 @@ export default class MessageEntrance extends Emiter { @@ -653,57 +633,60 @@ export default class MessageEntrance extends Emiter {
653 633
654 //ConferApe 634 //ConferApe
655 //开始上课 635 //开始上课
656 - _sendStartClass(_param){  
657 - if(!_mcu.connected){ 636 + _sendStartClass(_param) {
  637 + if (!_mcu.connected) {
658 loger.warn(GlobalConfig.getCurrentStatus()); 638 loger.warn(GlobalConfig.getCurrentStatus());
659 return; 639 return;
660 } 640 }
661 641
662 - if(_confer_ape){ 642 + if (_confer_ape) {
663 _confer_ape.startClass(_param); 643 _confer_ape.startClass(_param);
664 } 644 }
665 } 645 }
  646 +
666 //暂停上课 647 //暂停上课
667 - _sendPauseClass(_param){  
668 - if(!_mcu.connected){ 648 + _sendPauseClass(_param) {
  649 + if (!_mcu.connected) {
669 loger.warn(GlobalConfig.getCurrentStatus()); 650 loger.warn(GlobalConfig.getCurrentStatus());
670 return; 651 return;
671 } 652 }
672 - if(_confer_ape){ 653 + if (_confer_ape) {
673 _confer_ape.pauseClass(_param); 654 _confer_ape.pauseClass(_param);
674 } 655 }
675 } 656 }
  657 +
676 //停止上课 658 //停止上课
677 - _sendCloseClass(_param){  
678 - if(!_mcu.connected){ 659 + _sendCloseClass(_param) {
  660 + if (!_mcu.connected) {
679 loger.warn(GlobalConfig.getCurrentStatus()); 661 loger.warn(GlobalConfig.getCurrentStatus());
680 return; 662 return;
681 } 663 }
682 - if(_confer_ape){ 664 + if (_confer_ape) {
683 _confer_ape.closeClass(_param); 665 _confer_ape.closeClass(_param);
684 } 666 }
685 } 667 }
686 - // 离开会议 668 +
  669 + // 离开课堂
687 _leaveClass() { 670 _leaveClass() {
688 - if(!_mcu.connected){ 671 + if (!_mcu.connected) {
689 loger.warn(GlobalConfig.getCurrentStatus()); 672 loger.warn(GlobalConfig.getCurrentStatus());
690 return; 673 return;
691 } 674 }
692 675
693 //停止推流 676 //停止推流
694 - if(_video_ape){ 677 + if (_video_ape) {
695 _video_ape.stopPublishVideo(); 678 _video_ape.stopPublishVideo();
696 } 679 }
697 - if(_audio_ape){ 680 + if (_audio_ape) {
698 _audio_ape.stopPublishAudio(); 681 _audio_ape.stopPublishAudio();
699 } 682 }
700 - //离开会议  
701 - if(_confer_ape){ 683 + //离开课堂
  684 + if (_confer_ape) {
702 _confer_ape.stopRecord(); 685 _confer_ape.stopRecord();
703 _confer_ape.leaveClass(); 686 _confer_ape.leaveClass();
704 } 687 }
705 //断开MCU连接 688 //断开MCU连接
706 - if(_mcu){ 689 + if (_mcu) {
707 _mcu.leaveMCU(); 690 _mcu.leaveMCU();
708 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3); 691 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3);
709 } 692 }
@@ -713,13 +696,13 @@ export default class MessageEntrance extends Emiter { @@ -713,13 +696,13 @@ export default class MessageEntrance extends Emiter {
713 //ChatApe 696 //ChatApe
714 // 发送聊天消息 697 // 发送聊天消息
715 _sendChatMsg(_messageInfo) { 698 _sendChatMsg(_messageInfo) {
716 - if(!_mcu.connected){ 699 + if (!_mcu.connected) {
717 loger.warn(GlobalConfig.getCurrentStatus()); 700 loger.warn(GlobalConfig.getCurrentStatus());
718 return; 701 return;
719 } 702 }
720 - if(_messageInfo===null||EngineUtils.isEmptyObject(_messageInfo)){  
721 - loger.log('sendChatMsg 传递的参数不对',_messageInfo);  
722 - return ; 703 + if (_messageInfo === null || EngineUtils.isEmptyObject(_messageInfo)) {
  704 + loger.log('sendChatMsg 传递的参数不对', _messageInfo);
  705 + return;
723 } 706 }
724 if (_chat_ape) { 707 if (_chat_ape) {
725 _chat_ape.sendChatMsg(_messageInfo); 708 _chat_ape.sendChatMsg(_messageInfo);
@@ -727,101 +710,113 @@ export default class MessageEntrance extends Emiter { @@ -727,101 +710,113 @@ export default class MessageEntrance extends Emiter {
727 } 710 }
728 711
729 //VidoeApe 712 //VidoeApe
730 - videoUpdate(_data){ 713 + videoUpdate(_data) {
731 //视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态 714 //视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
732 - if(_confer_ape){ 715 + if (_confer_ape) {
733 _confer_ape.updaterRosterStatus(_data); 716 _confer_ape.updaterRosterStatus(_data);
734 } 717 }
735 } 718 }
736 719
737 - _sendVideoBroadcastMsg(_param){  
738 - if(!_mcu.connected){ 720 + _sendVideoBroadcastMsg(_param) {
  721 + if (!_mcu.connected) {
739 loger.warn(GlobalConfig.getCurrentStatus()); 722 loger.warn(GlobalConfig.getCurrentStatus());
740 return; 723 return;
741 } 724 }
742 - if(_video_ape){ 725 + if (_video_ape) {
743 return _video_ape.sendVideoBroadcastMsg(_param); 726 return _video_ape.sendVideoBroadcastMsg(_param);
744 } 727 }
745 } 728 }
746 729
747 - _getVideoPlayPath(_param){  
748 - if(_video_ape){ 730 + _getVideoPlayPath(_param) {
  731 + if (_video_ape) {
749 return _video_ape.getPlayVideoPath(_param); 732 return _video_ape.getPlayVideoPath(_param);
750 } 733 }
751 } 734 }
752 735
753 - _getVideoPublishPath(_param){  
754 - if(_video_ape){ 736 + _getVideoPublishPath(_param) {
  737 + if (_video_ape) {
755 return _video_ape.getPublishVideoPath(_param); 738 return _video_ape.getPublishVideoPath(_param);
756 } 739 }
757 } 740 }
758 741
759 - _publishVideo(_param){  
760 - if(!_mcu.connected){ 742 + _getVideoAllChannelInfo(_param) {
  743 + if (_video_ape) {
  744 + return _video_ape.getAllChannelInfo(_param);
  745 + }
  746 + }
  747 +
  748 + _publishVideo(_param) {
  749 + if (!_mcu.connected) {
761 loger.warn(GlobalConfig.getCurrentStatus()); 750 loger.warn(GlobalConfig.getCurrentStatus());
762 return; 751 return;
763 } 752 }
764 - if(_video_ape){ 753 + if (_video_ape) {
765 return _video_ape.publishVideo(_param); 754 return _video_ape.publishVideo(_param);
766 } 755 }
767 } 756 }
768 757
769 - _stopPublishVideo(_param){  
770 - if(!_mcu.connected){ 758 + _stopPublishVideo(_param) {
  759 + if (!_mcu.connected) {
771 loger.warn(GlobalConfig.getCurrentStatus()); 760 loger.warn(GlobalConfig.getCurrentStatus());
772 return; 761 return;
773 } 762 }
774 - if(_video_ape){ 763 + if (_video_ape) {
775 return _video_ape.stopPublishVideo(_param); 764 return _video_ape.stopPublishVideo(_param);
776 } 765 }
777 } 766 }
778 767
779 //AudioApe 768 //AudioApe
780 - audioUpdate(_data){ 769 + audioUpdate(_data) {
781 //音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态 770 //音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
782 - if(_confer_ape){ 771 + if (_confer_ape) {
783 _confer_ape.updaterRosterStatus(_data); 772 _confer_ape.updaterRosterStatus(_data);
784 } 773 }
785 } 774 }
786 775
787 - sendAudioCommandMsg(_param){  
788 - if(!_mcu.connected){ 776 + sendAudioCommandMsg(_param) {
  777 + if (!_mcu.connected) {
789 loger.warn(GlobalConfig.getCurrentStatus()); 778 loger.warn(GlobalConfig.getCurrentStatus());
790 return; 779 return;
791 } 780 }
792 - if(_audio_ape){ 781 + if (_audio_ape) {
793 return _audio_ape.sendAudioBroadcastMsg(_param); 782 return _audio_ape.sendAudioBroadcastMsg(_param);
794 } 783 }
795 } 784 }
796 785
797 - _getPlayAudioPath(_param){  
798 - if(_audio_ape){ 786 + _getPlayAudioPath(_param) {
  787 + if (_audio_ape) {
799 return _audio_ape.getAudioPlayPath(_param); 788 return _audio_ape.getAudioPlayPath(_param);
800 } 789 }
801 } 790 }
802 791
803 - _getPublishAudioPath(_param){  
804 - if(_audio_ape){ 792 + _getPublishAudioPath(_param) {
  793 + if (_audio_ape) {
805 return _audio_ape.getAudioPublishPath(_param); 794 return _audio_ape.getAudioPublishPath(_param);
806 } 795 }
807 } 796 }
808 797
809 - _publishAudio(_param){  
810 - if(!_mcu.connected){ 798 + _getAudioAllChannelInfo(_param) {
  799 + if (_audio_ape) {
  800 + return _audio_ape.getAllChannelInfo(_param);
  801 + }
  802 + }
  803 +
  804 + _publishAudio(_param) {
  805 + if (!_mcu.connected) {
811 loger.warn(GlobalConfig.getCurrentStatus()); 806 loger.warn(GlobalConfig.getCurrentStatus());
812 return; 807 return;
813 } 808 }
814 - if(_audio_ape){ 809 + if (_audio_ape) {
815 return _audio_ape.publishAudio(_param); 810 return _audio_ape.publishAudio(_param);
816 } 811 }
817 } 812 }
818 813
819 - _stopPublishAudio(_param){  
820 - if(!_mcu.connected){ 814 + _stopPublishAudio(_param) {
  815 + if (!_mcu.connected) {
821 loger.warn(GlobalConfig.getCurrentStatus()); 816 loger.warn(GlobalConfig.getCurrentStatus());
822 return; 817 return;
823 } 818 }
824 - if(_audio_ape){ 819 + if (_audio_ape) {
825 return _audio_ape.stopPublishAudio(_param); 820 return _audio_ape.stopPublishAudio(_param);
826 } 821 }
827 } 822 }
@@ -829,49 +824,52 @@ export default class MessageEntrance extends Emiter { @@ -829,49 +824,52 @@ export default class MessageEntrance extends Emiter {
829 824
830 //WhiteBoardApe 825 //WhiteBoardApe
831 // 添加标注,发送信息 826 // 添加标注,发送信息
832 - _sendInsertAnnotaion(_param){  
833 - if(!_mcu.connected){ 827 + _sendInsertAnnotaion(_param) {
  828 + if (!_mcu.connected) {
834 loger.warn(GlobalConfig.getCurrentStatus()); 829 loger.warn(GlobalConfig.getCurrentStatus());
835 return; 830 return;
836 } 831 }
837 - if(_whiteboard_ape){ 832 + if (_whiteboard_ape) {
838 _whiteboard_ape.sendInsetAnnotaion(_param); 833 _whiteboard_ape.sendInsetAnnotaion(_param);
839 } 834 }
840 } 835 }
841 836
842 //删除标注,发送信息 837 //删除标注,发送信息
843 - _sendDeleteAnnotaion(_param){  
844 - if(!_mcu.connected){ 838 + _sendDeleteAnnotaion(_param) {
  839 + if (!_mcu.connected) {
845 loger.warn(GlobalConfig.getCurrentStatus()); 840 loger.warn(GlobalConfig.getCurrentStatus());
846 return; 841 return;
847 } 842 }
848 - if(_whiteboard_ape){ 843 + if (_whiteboard_ape) {
849 _whiteboard_ape.sendDeleteAnnotaion(_param); 844 _whiteboard_ape.sendDeleteAnnotaion(_param);
850 } 845 }
851 } 846 }
  847 +
852 //删除当前页面上的所有标注 848 //删除当前页面上的所有标注
853 - _sendDeleteCurPageAnnotation(_param){  
854 - if(!_mcu.connected){ 849 + _sendDeleteCurPageAnnotation(_param) {
  850 + if (!_mcu.connected) {
855 loger.warn(GlobalConfig.getCurrentStatus()); 851 loger.warn(GlobalConfig.getCurrentStatus());
856 return; 852 return;
857 } 853 }
858 - if(_whiteboard_ape){ 854 + if (_whiteboard_ape) {
859 _whiteboard_ape.sendDeleteCurPageAnnotation(_param); 855 _whiteboard_ape.sendDeleteCurPageAnnotation(_param);
860 } 856 }
861 } 857 }
  858 +
862 //删除所有标注 859 //删除所有标注
863 - _sendDeleteAllAnnotation(_param){  
864 - if(!_mcu.connected){ 860 + _sendDeleteAllAnnotation(_param) {
  861 + if (!_mcu.connected) {
865 loger.warn(GlobalConfig.getCurrentStatus()); 862 loger.warn(GlobalConfig.getCurrentStatus());
866 return; 863 return;
867 } 864 }
868 - if(_whiteboard_ape){ 865 + if (_whiteboard_ape) {
869 _whiteboard_ape.sendDeleteAllAnnotation(_param); 866 _whiteboard_ape.sendDeleteAllAnnotation(_param);
870 } 867 }
871 } 868 }
  869 +
872 //返回上一步标注 870 //返回上一步标注
873 - _sendGotoPrev(_param){  
874 - if(_whiteboard_ape){ 871 + _sendGotoPrev(_param) {
  872 + if (_whiteboard_ape) {
875 _whiteboard_ape.sendGotoPrev(_param); 873 _whiteboard_ape.sendGotoPrev(_param);
876 } 874 }
877 } 875 }
@@ -879,112 +877,119 @@ export default class MessageEntrance extends Emiter { @@ -879,112 +877,119 @@ export default class MessageEntrance extends Emiter {
879 877
880 //DocApe 878 //DocApe
881 //获取文档完整路径 879 //获取文档完整路径
882 - _getDocImageFullPath(_param){  
883 - if(_doc_ape){ 880 + _getDocImageFullPath(_param) {
  881 + if (_doc_ape) {
884 return _doc_ape.getDocImageFullPath(_param); 882 return _doc_ape.getDocImageFullPath(_param);
885 - }else { 883 + } else {
886 loger.error("文档模块还没有创建,无法获取"); 884 loger.error("文档模块还没有创建,无法获取");
887 return []; 885 return [];
888 } 886 }
889 } 887 }
890 - _getDocPDFFullPath(_param){  
891 - if(_doc_ape){ 888 +
  889 + _getDocPDFFullPath(_param) {
  890 + if (_doc_ape) {
892 return _doc_ape.getDocPDFFullPath(_param); 891 return _doc_ape.getDocPDFFullPath(_param);
893 - }else { 892 + } else {
894 loger.error("文档模块还没有创建,无法获取"); 893 loger.error("文档模块还没有创建,无法获取");
895 return []; 894 return [];
896 } 895 }
897 } 896 }
  897 +
898 //上传文档 898 //上传文档
899 - _sendDocumentUpload(_param){  
900 - if(!_mcu.connected){ 899 + _sendDocumentUpload(_param) {
  900 + if (!_mcu.connected) {
901 loger.warn(GlobalConfig.getCurrentStatus()); 901 loger.warn(GlobalConfig.getCurrentStatus());
902 return; 902 return;
903 } 903 }
904 - if(_doc_ape){ 904 + if (_doc_ape) {
905 _doc_ape.documentUpload(_param); 905 _doc_ape.documentUpload(_param);
906 } 906 }
907 } 907 }
  908 +
908 //切换文档 909 //切换文档
909 - _sendDocumentSwitchDoc(_param){  
910 - if(!_mcu.connected){ 910 + _sendDocumentSwitchDoc(_param) {
  911 + if (!_mcu.connected) {
911 loger.warn(GlobalConfig.getCurrentStatus()); 912 loger.warn(GlobalConfig.getCurrentStatus());
912 return; 913 return;
913 } 914 }
914 - if(_doc_ape){ 915 + if (_doc_ape) {
915 _doc_ape.documentSwitchDoc(_param); 916 _doc_ape.documentSwitchDoc(_param);
916 } 917 }
917 } 918 }
  919 +
918 //操作文档(翻页) 920 //操作文档(翻页)
919 - _sendDocumentSwitchPage(_param){  
920 - if(!_mcu.connected){ 921 + _sendDocumentSwitchPage(_param) {
  922 + if (!_mcu.connected) {
921 loger.warn(GlobalConfig.getCurrentStatus()); 923 loger.warn(GlobalConfig.getCurrentStatus());
922 return; 924 return;
923 } 925 }
924 - if(_doc_ape){ 926 + if (_doc_ape) {
925 _doc_ape.documentSwitchPage(_param); 927 _doc_ape.documentSwitchPage(_param);
926 } 928 }
927 } 929 }
  930 +
928 //操作文档(缩放、滚动...) 931 //操作文档(缩放、滚动...)
929 - _sendDocumentCommand(_param){  
930 - if(!_mcu.connected){ 932 + _sendDocumentCommand(_param) {
  933 + if (!_mcu.connected) {
931 loger.warn(GlobalConfig.getCurrentStatus()); 934 loger.warn(GlobalConfig.getCurrentStatus());
932 return; 935 return;
933 } 936 }
934 - if(_doc_ape){ 937 + if (_doc_ape) {
935 _doc_ape.documentCommand(_param); 938 _doc_ape.documentCommand(_param);
936 } 939 }
937 } 940 }
  941 +
938 //删除文档 942 //删除文档
939 - _sendDocumentDelete(_param){  
940 - if(!_mcu.connected){ 943 + _sendDocumentDelete(_param) {
  944 + if (!_mcu.connected) {
941 loger.warn(GlobalConfig.getCurrentStatus()); 945 loger.warn(GlobalConfig.getCurrentStatus());
942 return; 946 return;
943 } 947 }
944 - if(_doc_ape){ 948 + if (_doc_ape) {
945 _doc_ape.documentDelete(_param); 949 _doc_ape.documentDelete(_param);
946 } 950 }
947 } 951 }
  952 +
948 //删除所有文档 953 //删除所有文档
949 - _documentDeleteAll(_param){  
950 - if(!_mcu.connected){ 954 + _documentDeleteAll(_param) {
  955 + if (!_mcu.connected) {
951 loger.warn(GlobalConfig.getCurrentStatus()); 956 loger.warn(GlobalConfig.getCurrentStatus());
952 return; 957 return;
953 } 958 }
954 - if(_doc_ape){ 959 + if (_doc_ape) {
955 _doc_ape.documentDeleteAll(_param); 960 _doc_ape.documentDeleteAll(_param);
956 } 961 }
957 } 962 }
958 963
959 //// 文档变更,白板也需要做处理 964 //// 文档变更,白板也需要做处理
960 docUpdateHandler(_data) { 965 docUpdateHandler(_data) {
961 - if(!_mcu.connected){ 966 + if (!_mcu.connected) {
962 loger.warn(GlobalConfig.getCurrentStatus()); 967 loger.warn(GlobalConfig.getCurrentStatus());
963 return; 968 return;
964 } 969 }
965 loger.log('Doc UpdateId ->'); 970 loger.log('Doc UpdateId ->');
966 - console.log(_data);  
967 - if(_whiteboard_ape){ 971 + loger.log(_data);
  972 + if (_whiteboard_ape) {
968 _whiteboard_ape.docUpdateHandler(_data); 973 _whiteboard_ape.docUpdateHandler(_data);
969 } 974 }
970 } 975 }
971 976
972 //文档删除,白板也需要做处理 977 //文档删除,白板也需要做处理
973 - docDeleteHandler(_data){  
974 - if(_whiteboard_ape){ 978 + docDeleteHandler(_data) {
  979 + if (_whiteboard_ape) {
975 _whiteboard_ape.docDeleteHandler(_data); 980 _whiteboard_ape.docDeleteHandler(_data);
976 } 981 }
977 } 982 }
978 983
979 //文档加入频道成功,同步到MCU服务器上的数据 984 //文档加入频道成功,同步到MCU服务器上的数据
980 - docJoinChannelSuccess(){  
981 - loger.log("docJoinChannelSuccess isHost=",GlobalConfig.isHost);  
982 - console.log(GlobalConfig.docListPrepare); 985 + docJoinChannelSuccess() {
  986 + loger.log("docJoinChannelSuccess isHost=", GlobalConfig.isHost);
  987 + loger.log(GlobalConfig.docListPrepare);
983 loger.log("docJoinChannelSuccess docListPrepare="); 988 loger.log("docJoinChannelSuccess docListPrepare=");
984 //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传 989 //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传
985 - if(GlobalConfig.isHost){  
986 - for (let value of GlobalConfig.docListPrepare){  
987 - if(value){ 990 + if (GlobalConfig.isHost) {
  991 + for (let value of GlobalConfig.docListPrepare) {
  992 + if (value) {
988 /* //提前上传的文档文档信息的结构 993 /* //提前上传的文档文档信息的结构
989 { 994 {
990 "MD5": "f3feb3fac8cd3a953bded00e07a0c66b", 995 "MD5": "f3feb3fac8cd3a953bded00e07a0c66b",
@@ -1011,16 +1016,16 @@ export default class MessageEntrance extends Emiter { @@ -1011,16 +1016,16 @@ export default class MessageEntrance extends Emiter {
1011 "uploadStartTime": "2017-02-03 11:54:27" 1016 "uploadStartTime": "2017-02-03 11:54:27"
1012 }*/ 1017 }*/
1013 1018
1014 - loger.log("判断是否需要把提前上传的文档上传到mcu",value);  
1015 - let paramInfo={ 1019 + loger.log("判断是否需要把提前上传的文档上传到mcu", value);
  1020 + let paramInfo = {
1016 "pageNum": value.pdfSize, 1021 "pageNum": value.pdfSize,
1017 "fileName": value.name, 1022 "fileName": value.name,
1018 "fileType": value.type, 1023 "fileType": value.type,
1019 "relativeUrl": value.relativeLocation, 1024 "relativeUrl": value.relativeLocation,
1020 "url": value.absoluteLocation, 1025 "url": value.absoluteLocation,
1021 - "creatUserId":value.createUserID, 1026 + "creatUserId": value.createUserID,
1022 "docId": value.id, 1027 "docId": value.id,
1023 - "md5":value.MD5, 1028 + "md5": value.MD5,
1024 "visible": false 1029 "visible": false
1025 }; 1030 };
1026 1031
@@ -1029,4 +1034,116 @@ export default class MessageEntrance extends Emiter { @@ -1029,4 +1034,116 @@ export default class MessageEntrance extends Emiter {
1029 } 1034 }
1030 } 1035 }
1031 } 1036 }
  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 + }
  1067 + }
  1068 +
  1069 + //开始录制回放
  1070 + _startRecordPlayback(_param) {
  1071 + if (_parseBuf) {
  1072 + _parseBuf.startRecordPlayback(_param);
  1073 + }
  1074 + }
  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 + }
  1086 + }
  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,6 +394,10 @@ class Sass extends Emiter { @@ -383,6 +394,10 @@ 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"; 402 let key = "3mang123A";
388 let siteID = GlobalConfig.siteId; 403 let siteID = GlobalConfig.siteId;
@@ -390,16 +405,16 @@ class Sass extends Emiter { @@ -390,16 +405,16 @@ class Sass extends Emiter {
390 let userID = GlobalConfig.userId; 405 let userID = GlobalConfig.userId;
391 let userName = GlobalConfig.userName; 406 let userName = GlobalConfig.userName;
392 let meetingName = GlobalConfig.className; 407 let meetingName = GlobalConfig.className;
393 - let startTime =GlobalConfig.classBeginTime; 408 + let startTime = GlobalConfig.classBeginTime;
394 let endTime = GlobalConfig.classEndTime; 409 let endTime = GlobalConfig.classEndTime;
395 let playUrl = ""; 410 let playUrl = "";
396 let streamName = GlobalConfig.recordFileName; 411 let streamName = GlobalConfig.recordFileName;
397 - let confRecordFileName=GlobalConfig.recordFileName; 412 + let confRecordFileName = GlobalConfig.recordFileName;
398 let downloadUrl = ""; 413 let downloadUrl = "";
399 let recordStatus = GlobalConfig.classStatus; 414 let recordStatus = GlobalConfig.classStatus;
400 - let recordTimestamp =GlobalConfig.classTimestamp; 415 + let recordTimestamp = GlobalConfig.classTimestamp;
401 416
402 - let timestamp = new Date().getTime();; 417 + let timestamp = new Date().getTime();
403 let authId = MD5(key + siteID + meetingID + timestamp); 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);
@@ -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,23 +15,22 @@ @@ -15,23 +15,22 @@
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, 31 + constructor(session_id,
32 session_name, 32 session_name,
33 - session_tag  
34 - ) { 33 + session_tag) {
35 super(); 34 super();
36 this._session_id = session_id; 35 this._session_id = session_id;
37 this._channel_id = session_id; // session_id === channel_id 36 this._channel_id = session_id; // session_id === channel_id
@@ -52,58 +51,49 @@ export default class Ape extends Emiter { @@ -52,58 +51,49 @@ export default class Ape extends Emiter {
52 51
53 //先收到onJoinSessionHandlerSuccess 后收到 onJoinChannelHandlerSuccess 52 //先收到onJoinSessionHandlerSuccess 后收到 onJoinChannelHandlerSuccess
54 53
55 - // 监听底层MCU会议  
56 - this.mcu = mcu; 54 + // 监听底层MCU课堂
  55 + this.mcu = McuObj;
57 this.mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuConferenceJoinSuccessHandler.bind(this)); 56 this.mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuConferenceJoinSuccessHandler.bind(this));
58 this.mcu.registerApe(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 +
59 } 64 }
60 65
61 regResponsePduHandler() { 66 regResponsePduHandler() {
62 67
63 } 68 }
64 69
  70 + //停止APE一切操作
  71 + stopApe() {
  72 + loger.log("stopApe==============================");
  73 + }
  74 +
65 // 消息处理 75 // 消息处理
66 - _pduMessageHandler(regBuffer) {  
67 - //loger.log("RCPDU_REG_ADAPTER=============================="); 76 + _pduMessageHandler(regBuffer,_seekTime) {
  77 + let seekTime=_seekTime||0;//这个只有在录制回放的时候才有
  78 + //loger.log("RCPDU_REG_ADAPTER============seekTime",seekTime);
68 if (this._apeDelayed) { 79 if (this._apeDelayed) {
69 // this._apeDelayedMsgs.push(regBuffer); 80 // this._apeDelayedMsgs.push(regBuffer);
70 // this._apeDelayedStart(); 81 // this._apeDelayedStart();
71 setTimeout(() => { 82 setTimeout(() => {
72 - this._pduRegAdapterHandler(regBuffer);  
73 - },GlobalConfig.mcuDelay|| 12000); 83 + this._pduRegAdapterHandler(regBuffer,seekTime);
  84 + }, GlobalConfig.mcuDelay || 2000);
74 return; 85 return;
75 } 86 }
76 - this._pduRegAdapterHandler(regBuffer); 87 + this._pduRegAdapterHandler(regBuffer,seekTime);
77 } 88 }
78 89
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 // 数据同步处理 90 // 数据同步处理
99 - _pduRegAdapterHandler(regBuffer) { 91 + _pduRegAdapterHandler(regBuffer,seekTime) {
100 let regPdu = pdu['RCAdapterPdu'].decode(regBuffer); 92 let regPdu = pdu['RCAdapterPdu'].decode(regBuffer);
101 let regItems = regPdu.item; 93 let regItems = regPdu.item;
102 let regItemSize = regItems.length; 94 let regItemSize = regItems.length;
103 //loger.log(this._session_name + '数据同步消息'); 95 //loger.log(this._session_name + '数据同步消息');
104 - loger.log(this._session_name + '数据同步消息.同步条数', regItemSize);  
105 - //console.log(regPdu);  
106 - 96 + //loger.log(this._session_name + '数据同步消息.同步条数', regItemSize,"seekTime->",seekTime);
107 for (var i = 0; i < regItemSize; ++i) { 97 for (var i = 0; i < regItemSize; ++i) {
108 let regItem = regItems[i]; 98 let regItem = regItems[i];
109 let regItemType = regItem.type; 99 let regItemType = regItem.type;
@@ -172,13 +162,13 @@ export default class Ape extends Emiter { @@ -172,13 +162,13 @@ export default class Ape extends Emiter {
172 case pdu.RCPDU_REG_TABLE_UPDATE_PDU: 162 case pdu.RCPDU_REG_TABLE_UPDATE_PDU:
173 let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data); 163 let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data);
174 let tableUpdateItems = tableUpdateData.items; 164 let tableUpdateItems = tableUpdateData.items;
175 - let tableUpdateItemsLen= tableUpdateItems.length;  
176 - loger.log("RCRegistryTableUpdateItemPdu "+tableUpdateItemsLen);  
177 - console.log(tableUpdateData); 165 + let tableUpdateItemsLen = tableUpdateItems.length;
  166 + //loger.log("RCRegistryTableUpdateItemPdu " + tableUpdateItemsLen);
  167 + loger.log(tableUpdateData);
178 168
179 for (let i = 0; i < tableUpdateItemsLen; ++i) { 169 for (let i = 0; i < tableUpdateItemsLen; ++i) {
180 let tableItem = tableUpdateItems[i]; 170 let tableItem = tableUpdateItems[i];
181 - this.tableUpdateHandler(tableItem.owner, tableItem.itemIdx, tableItem.itemData); 171 + this.tableUpdateHandler(tableItem.owner, tableItem.itemIdx, tableItem.itemData,seekTime);
182 } 172 }
183 break; 173 break;
184 case pdu.RCPDU_REG_QUEUE_UPDATE_PDU: 174 case pdu.RCPDU_REG_QUEUE_UPDATE_PDU:
@@ -194,27 +184,35 @@ export default class Ape extends Emiter { @@ -194,27 +184,35 @@ export default class Ape extends Emiter {
194 rosterInsertHandler(recordId, recordData) { 184 rosterInsertHandler(recordId, recordData) {
195 loger.warn(this._session_name + ' rosterInsertHandler 应有子类具体覆盖处理.'); 185 loger.warn(this._session_name + ' rosterInsertHandler 应有子类具体覆盖处理.');
196 } 186 }
  187 +
197 rosterUpdateHandler(nodeId, nodeData) { 188 rosterUpdateHandler(nodeId, nodeData) {
198 loger.warn(this._session_name + ' rosterUpdateHandler 应有子类具体覆盖处理.'); 189 loger.warn(this._session_name + ' rosterUpdateHandler 应有子类具体覆盖处理.');
199 } 190 }
  191 +
200 rosterDelHandler(recordData) { 192 rosterDelHandler(recordData) {
201 loger.warn(this._session_name + ' rosterDelHandler 应有子类具体覆盖处理.'); 193 loger.warn(this._session_name + ' rosterDelHandler 应有子类具体覆盖处理.');
202 } 194 }
  195 +
203 tableInsertHandler(tableId, record) { 196 tableInsertHandler(tableId, record) {
204 loger.warn(this._session_name + ' tableInsertHandler 应有子类具体覆盖处理.'); 197 loger.warn(this._session_name + ' tableInsertHandler 应有子类具体覆盖处理.');
205 } 198 }
206 - tableUpdateHandler(ownerId, recordId, recordData) { 199 +
  200 + tableUpdateHandler(ownerId, recordId, recordData,seekTime) {
207 loger.warn(this._session_name + ' tableUpdateHandler 应有子类具体覆盖处理.'); 201 loger.warn(this._session_name + ' tableUpdateHandler 应有子类具体覆盖处理.');
208 } 202 }
  203 +
209 tableDeleteHandler(tableId, record) { 204 tableDeleteHandler(tableId, record) {
210 loger.warn(this._session_name + ' tableDelHandler 应有子类具体覆盖处理.'); 205 loger.warn(this._session_name + ' tableDelHandler 应有子类具体覆盖处理.');
211 } 206 }
212 - onJoinChannelHandlerSuccess(){ 207 +
  208 + onJoinChannelHandlerSuccess() {
213 loger.warn(this._session_name + ' onJoinChannelHandlerSuccess 应有子类具体覆盖处理.'); 209 loger.warn(this._session_name + ' onJoinChannelHandlerSuccess 应有子类具体覆盖处理.');
214 } 210 }
215 - onJoinSessionHandlerSuccess(){ 211 +
  212 + onJoinSessionHandlerSuccess() {
216 loger.warn(this._session_name + ' onJoinSessionHandlerSuccess 应有子类具体覆盖处理.'); 213 loger.warn(this._session_name + ' onJoinSessionHandlerSuccess 应有子类具体覆盖处理.');
217 } 214 }
  215 +
218 // 加入Session处理 216 // 加入Session处理
219 _joinSessionHandler(data) { 217 _joinSessionHandler(data) {
220 loger.log(this._session_name, ' -> 加入Session'); 218 loger.log(this._session_name, ' -> 加入Session');
@@ -233,7 +231,7 @@ export default class Ape extends Emiter { @@ -233,7 +231,7 @@ export default class Ape extends Emiter {
233 } 231 }
234 } 232 }
235 233
236 - // 依赖的会议创建完毕 - 发起Ape加入 234 + // 依赖的课堂创建完毕 - 发起Ape加入
237 _mcuConferenceJoinSuccessHandler(_data) { 235 _mcuConferenceJoinSuccessHandler(_data) {
238 loger.log('创建Ape->', 236 loger.log('创建Ape->',
239 'SessionId', 237 'SessionId',
@@ -243,7 +241,7 @@ export default class Ape extends Emiter { @@ -243,7 +241,7 @@ export default class Ape extends Emiter {
243 'SessionTag', 241 'SessionTag',
244 this._session_tag); 242 this._session_tag);
245 243
246 - // 会议依赖底层会议信息 244 + // 课堂依赖底层课堂信息
247 //this._classInfo = classInfo; 245 //this._classInfo = classInfo;
248 this._classInfo = GlobalConfig.getClassInfo(); 246 this._classInfo = GlobalConfig.getClassInfo();
249 247
@@ -260,6 +258,17 @@ export default class Ape extends Emiter { @@ -260,6 +258,17 @@ export default class Ape extends Emiter {
260 this.send(joinChannelPdu); 258 this.send(joinChannelPdu);
261 } 259 }
262 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);
  270 + }
  271 +
263 // 注册Key对象 272 // 注册Key对象
264 registerKey(id, name, tag, user_data) { 273 registerKey(id, name, tag, user_data) {
265 let adapterItemPdu = new pdu['RCAdapterItemPdu']; 274 let adapterItemPdu = new pdu['RCAdapterItemPdu'];
@@ -301,10 +310,10 @@ export default class Ape extends Emiter { @@ -301,10 +310,10 @@ export default class Ape extends Emiter {
301 310
302 send(appPdu) { 311 send(appPdu) {
303 loger.log('Ape发送数据NORMAL PDU'); 312 loger.log('Ape发送数据NORMAL PDU');
304 - console.log(appPdu); 313 + //console.log(appPdu);
305 //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code); 314 //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); 315 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  316 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
308 return; 317 return;
309 } 318 }
310 let normalPdu = pdu.create_normal_pdu( 319 let normalPdu = pdu.create_normal_pdu(
@@ -327,10 +336,10 @@ export default class Ape extends Emiter { @@ -327,10 +336,10 @@ export default class Ape extends Emiter {
327 // 发送当前APE(session uniform包) 336 // 发送当前APE(session uniform包)
328 sendUniform(appPdu, top) { 337 sendUniform(appPdu, top) {
329 loger.log('Ape发送数据UNIFORM PDU'); 338 loger.log('Ape发送数据UNIFORM PDU');
330 - console.log(appPdu); 339 + //console.log(appPdu);
331 //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code); 340 //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); 341 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  342 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
334 return; 343 return;
335 } 344 }
336 345
@@ -352,10 +361,10 @@ export default class Ape extends Emiter { @@ -352,10 +361,10 @@ export default class Ape extends Emiter {
352 361
353 sendChatUniform(appPdu, top) { 362 sendChatUniform(appPdu, top) {
354 loger.log('Ape发送数据UNIFORM PDU'); 363 loger.log('Ape发送数据UNIFORM PDU');
355 - console.log(appPdu); 364 + //console.log(appPdu);
356 //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code); 365 //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); 366 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  367 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
359 return; 368 return;
360 } 369 }
361 370
@@ -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;//(助教)
@@ -21,6 +21,7 @@ class AudioApe extends Ape { @@ -21,6 +21,7 @@ class AudioApe extends Ape {
21 ApeConsts.AUDIO_SESSION_TAG 21 ApeConsts.AUDIO_SESSION_TAG
22 ); 22 );
23 23
  24 + this.releaseTimeId=0
24 this.mediaModule=new MediaModule(); 25 this.mediaModule=new MediaModule();
25 this.mediaModule.MEDIA_OBJ_TABLE_ID=ApeConsts.AUDIO_OBJ_TABLE_ID; 26 this.mediaModule.MEDIA_OBJ_TABLE_ID=ApeConsts.AUDIO_OBJ_TABLE_ID;
26 this.mediaModule.mediaChannels={}; 27 this.mediaModule.mediaChannels={};
@@ -47,9 +48,19 @@ class AudioApe extends Ape { @@ -47,9 +48,19 @@ class AudioApe extends Ape {
47 //获取推流地址 48 //获取推流地址
48 getAudioPublishPath(_param) { 49 getAudioPublishPath(_param) {
49 loger.log('getAudioPublishPath'); 50 loger.log('getAudioPublishPath');
  51 + if(!this.mcu.connected){
  52 + loger.warn(GlobalConfig.getCurrentStatus());
  53 + return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};;
  54 + }
50 return this.mediaModule.getMediaPublishPath(_param); 55 return this.mediaModule.getMediaPublishPath(_param);
51 } 56 }
52 57
  58 + //获取当前所有频道信息
  59 + getAllChannelInfo(_param){
  60 + loger.log('getAllChannelInfo');
  61 + return this.mediaModule.getAllMediaChannelInfo();
  62 + }
  63 +
53 //推流 64 //推流
54 publishAudio(_param) { 65 publishAudio(_param) {
55 if(!this.mcu.connected){ 66 if(!this.mcu.connected){
@@ -71,18 +82,19 @@ class AudioApe extends Ape { @@ -71,18 +82,19 @@ class AudioApe extends Ape {
71 return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"}; 82 return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"};
72 } 83 }
73 84
74 - 85 + /* //20170302 修改频道占用规则,同一个人可以推多路流,暂停下面的限制
75 //同一个nodeId只允许推一个流,如果已经推了就不能再推 86 //同一个nodeId只允许推一个流,如果已经推了就不能再推
76 if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){ 87 if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){
77 loger.warn("publishAudio,已经存在一个流,不能再推"); 88 loger.warn("publishAudio,已经存在一个流,不能再推");
78 - return {"code": ApeConsts.RETURN_FAILED, "data": "已经存在一个流,不能再推"};  
79 - } 89 + return {"code": ApeConsts.RETURN_FAILED, "data": "已经存在一个流,不能再推","mediaChannels":this.mediaModule.mediaChannels};
  90 + }*/
  91 +
80 92
81 //判断当前是否还有空闲的channle 93 //判断当前是否还有空闲的channle
82 let freeChannel = this.mediaModule.getFreeMediaChannel(); 94 let freeChannel = this.mediaModule.getFreeMediaChannel();
83 if (freeChannel == 0) { 95 if (freeChannel == 0) {
84 loger.warn("publishAudio,没有空闲的channel "); 96 loger.warn("publishAudio,没有空闲的channel ");
85 - return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"}; 97 + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels};
86 } 98 }
87 99
88 //判断当前的频道是否已经占用 100 //判断当前的频道是否已经占用
@@ -91,33 +103,73 @@ class AudioApe extends Ape { @@ -91,33 +103,73 @@ class AudioApe extends Ape {
91 return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"}; 103 return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"};
92 } 104 }
93 105
94 - let channelInfo={}; 106 + let channelInfo=this.mediaModule.getDefaultChannelInfo();
  107 + channelInfo.owner=GlobalConfig.nodeId;
95 channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING; 108 channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING;
96 - channelInfo.fromNodeId=GlobalConfig.nodeId;  
97 channelInfo.channelId=needPublishChannelInfo.channelId;//freeChannel 109 channelInfo.channelId=needPublishChannelInfo.channelId;//freeChannel
98 channelInfo.streamId=needPublishChannelInfo.streamId;//按规则拼接的流名称 110 channelInfo.streamId=needPublishChannelInfo.streamId;//按规则拼接的流名称
99 channelInfo.timestamp=needPublishChannelInfo.timestamp;//EngineUtils.creatTimestamp(); 111 channelInfo.timestamp=needPublishChannelInfo.timestamp;//EngineUtils.creatTimestamp();
100 - channelInfo.classId=GlobalConfig.classId;//GlobalConfig.classId;  
101 - channelInfo.siteId=GlobalConfig.siteId;//GlobalConfig.siteId;  
102 - channelInfo.toNodeId=0;  
103 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO; 112 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO;
104 this.sendTableUpdateHandler(channelInfo); 113 this.sendTableUpdateHandler(channelInfo);
105 - return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!"} 114 + return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId};
106 } 115 }
107 116
108 //停止推流, 117 //停止推流,
109 stopPublishAudio(_param) { 118 stopPublishAudio(_param) {
110 - loger.log('stopPublishAudio'); 119 + loger.log('stopPublishAudio ->_param',_param);
111 if(!this.mcu.connected){ 120 if(!this.mcu.connected){
112 loger.warn(GlobalConfig.getCurrentStatus()); 121 loger.warn(GlobalConfig.getCurrentStatus());
113 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; 122 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
114 } 123 }
115 - //_param如果为空或者0,那么默认就是当前自己的nodeId,否则用_param  
116 - let nodeId; 124 +
  125 + //默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
  126 + let nodeId=GlobalConfig.nodeId;
117 if(_param&&parseInt(_param.nodeId)>0){ 127 if(_param&&parseInt(_param.nodeId)>0){
118 nodeId=parseInt(_param.nodeId); 128 nodeId=parseInt(_param.nodeId);
  129 + }
  130 +
  131 + //默认为0,如果releaseChannelId 存在就释放releaseChannelId通道
  132 + let releaseChannelId=0;
  133 + if(_param&&parseInt(_param.mediaId)>0){
  134 + releaseChannelId=parseInt(_param.mediaId);
  135 + }
  136 +
  137 + //释放channelId 的占用
  138 + if(releaseChannelId>0){
  139 + //第一种情况,释放nodeId占用的指定mediaId (channelId)
  140 + this._releaseChannelForNodeId(nodeId,releaseChannelId);
119 }else { 141 }else {
120 - nodeId=GlobalConfig.nodeId; 142 + //第二种情况,释放nodeId占用的所有channelId
  143 + this._releaseNodeIdAllChannel(nodeId);
  144 + }
  145 + }
  146 +
  147 + //释放nodeId占用的指定的channelId频道
  148 + _releaseChannelForNodeId(nodeId,channelId){
  149 + loger.log(nodeId,"_releaseChannelForNodeId-->channelId",channelId);
  150 + let channelInfo=this.mediaModule.mediaChannels[channelId];
  151 + if(channelInfo&&channelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
  152 + if(channelInfo.fromNodeId==nodeId){
  153 +
  154 + let channelInfo=this.mediaModule.getDefaultChannelInfo();
  155 + channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
  156 + channelInfo.channelId=channelId;
  157 +
  158 + this.sendTableUpdateHandler(channelInfo);
  159 + }else {
  160 + loger.warn(channelId,"不属于nodeId",nodeId,"不能释放",channelInfo);
  161 + }
  162 + }else {
  163 + loger.warn(nodeId,"要释放的channel不存在或者已经释放-->channelId",channelInfo);
  164 + }
  165 + }
  166 + //释放nodeId占用的所有频道
  167 + _releaseNodeIdAllChannel(nodeId){
  168 + loger.log(nodeId,"_releaseNodeIdAllChannel",this.mcu.connected);
  169 + if(!this.mcu.connected){
  170 + clearTimeout(this.releaseTimeId);
  171 + loger.warn(GlobalConfig.getCurrentStatus());
  172 + return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
121 } 173 }
122 174
123 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); 175 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
@@ -126,18 +178,19 @@ class AudioApe extends Ape { @@ -126,18 +178,19 @@ class AudioApe extends Ape {
126 return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"}; 178 return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"};
127 } 179 }
128 180
129 - let channelInfo={}; 181 + let channelInfo=this.mediaModule.getDefaultChannelInfo();
130 channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED; 182 channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
131 - channelInfo.fromNodeId=0;  
132 channelInfo.channelId=openingChannel; 183 channelInfo.channelId=openingChannel;
133 - channelInfo.timestamp=0;  
134 - channelInfo.classId=GlobalConfig.classId;  
135 - channelInfo.toNodeId=0;  
136 - channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT; 184 +
137 this.sendTableUpdateHandler(channelInfo); 185 this.sendTableUpdateHandler(channelInfo);
  186 + //递归检查,800毫秒之后执行
  187 + this.releaseTimeId=setTimeout(function(){
  188 + loger.warn(nodeId,"递归检查频道是否占用");
  189 + this._releaseNodeIdAllChannel(nodeId);
  190 + }.bind(this),800);
138 } 191 }
139 -  
140 sendAudioBroadcastMsg(_param) { 192 sendAudioBroadcastMsg(_param) {
  193 + loger.log('sendAudioBroadcastMsg',_param);
141 if(!this.mcu.connected){ 194 if(!this.mcu.connected){
142 loger.warn(GlobalConfig.getCurrentStatus()); 195 loger.warn(GlobalConfig.getCurrentStatus());
143 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; 196 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
@@ -163,7 +216,7 @@ class AudioApe extends Ape { @@ -163,7 +216,7 @@ class AudioApe extends Ape {
163 let freeChannel = this.mediaModule.getFreeMediaChannel(); 216 let freeChannel = this.mediaModule.getFreeMediaChannel();
164 if (freeChannel == 0) { 217 if (freeChannel == 0) {
165 loger.warn('sendAudioBroadcastMsg,不能再打开更多的设备', _param); 218 loger.warn('sendAudioBroadcastMsg,不能再打开更多的设备', _param);
166 - return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"}; 219 + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels};
167 } 220 }
168 } 221 }
169 222
@@ -173,7 +226,7 @@ class AudioApe extends Ape { @@ -173,7 +226,7 @@ class AudioApe extends Ape {
173 audioSendPdu.isPublic = true; 226 audioSendPdu.isPublic = true;
174 227
175 audioSendPdu.fromNodeId = GlobalConfig.nodeId;//发起人 228 audioSendPdu.fromNodeId = GlobalConfig.nodeId;//发起人
176 - audioSendPdu.toNodeId = parseInt(_param.toNodeID) || 0;//接收者,0就是所有人 229 + audioSendPdu.toNodeId = parseInt(_param.toNodeId) || 0;//接收者,0就是所有人
177 audioSendPdu.actionType = parseInt(_param.actionType) || ApeConsts.MEDIA_ACTION_DEFAULT; 230 audioSendPdu.actionType = parseInt(_param.actionType) || ApeConsts.MEDIA_ACTION_DEFAULT;
178 231
179 audioSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" + _param.data);//开头两个字会乱码 232 audioSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" + _param.data);//开头两个字会乱码
@@ -200,14 +253,12 @@ class AudioApe extends Ape { @@ -200,14 +253,12 @@ class AudioApe extends Ape {
200 253
201 let tableItemPdu = new pdu['RCRegistryTableItemPdu']; 254 let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
202 tableItemPdu.itemIdx = _channelInfo.channelId; 255 tableItemPdu.itemIdx = _channelInfo.channelId;
203 - tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定 256 + tableItemPdu.owner = _channelInfo.owner;//0收到flash的是这个值,MCU做了了用户掉线处理,30秒之后会清理owner为0
204 tableItemPdu.itemData = updateModelPdu.toArrayBuffer(); 257 tableItemPdu.itemData = updateModelPdu.toArrayBuffer();
205 258
206 //insert 259 //insert
207 let tableInsertItemPdu = new pdu['RCRegistryTableUpdateItemPdu']; 260 let tableInsertItemPdu = new pdu['RCRegistryTableUpdateItemPdu'];
208 - //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];  
209 - //repeated RCRegistryTableItemPdu items = 2;  
210 - tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;// 261 + tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;
211 tableInsertItemPdu.items.push(tableItemPdu); 262 tableInsertItemPdu.items.push(tableItemPdu);
212 263
213 let updateObjPdu = new pdu['RCRegistryUpdateObjPdu']; 264 let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
@@ -248,27 +299,36 @@ class AudioApe extends Ape { @@ -248,27 +299,36 @@ class AudioApe extends Ape {
248 } 299 }
249 } 300 }
250 301
251 - tableUpdateHandler(owner, itemIdx, itemData) {  
252 - // debugger;  
253 - /* let updateChannelInfo = this.unPackPdu(owner, itemIdx, itemData);  
254 -  
255 - this.mediaModule.mediaChannels[itemIdx] = updateChannelInfo;  
256 -  
257 - this._emit(MessageTypes.AUDIO_UPDATE, updateChannelInfo);*/ 302 + tableUpdateHandler(owner, itemIdx, itemData,seek) {
258 let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData); 303 let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
  304 + loger.log("tableUpdateHandler->channel",itemIdx,'status->',unpackChannelInfo.status,"seek->",seek);
  305 + //****很重要********
  306 + //如果owner的值为0,代表的是这个歌频道已经被释放了(mcu服务端对于占用channel的掉线用户,就是把owner设置为0)
  307 + if(owner==0){
  308 + loger.log("释放占用的频道,channel",itemIdx);
  309 + unpackChannelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
  310 + unpackChannelInfo.streamId="";
  311 + }
  312 +
259 this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo; 313 this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
260 314
261 if(unpackChannelInfo&&unpackChannelInfo.fromNodeId!=GlobalConfig.nodeId){ 315 if(unpackChannelInfo&&unpackChannelInfo.fromNodeId!=GlobalConfig.nodeId){
262 let receiveChannelInfo={}; 316 let receiveChannelInfo={};
263 receiveChannelInfo.mediaId=unpackChannelInfo.channelId; 317 receiveChannelInfo.mediaId=unpackChannelInfo.channelId;
  318 + receiveChannelInfo.fromNodeId=unpackChannelInfo.fromNodeId;
264 319
265 //消息不是自己同步的,需要处理 320 //消息不是自己同步的,需要处理
266 if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){ 321 if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
267 //正在推流 322 //正在推流
268 receiveChannelInfo.m3u8Url=""; 323 receiveChannelInfo.m3u8Url="";
269 receiveChannelInfo.rtmpUrl=""; 324 receiveChannelInfo.rtmpUrl="";
  325 + receiveChannelInfo.replay="";
  326 +
  327 + receiveChannelInfo.seek=seek||0;//这个是录制回放时使用的seek
  328 +
270 let m3u8Stream=this.mediaModule.getMediaPlayPath({"type":"m3u8","streamId": unpackChannelInfo.streamId}); 329 let m3u8Stream=this.mediaModule.getMediaPlayPath({"type":"m3u8","streamId": unpackChannelInfo.streamId});
271 let rtmpStream=this.mediaModule.getMediaPlayPath({"type":"rtmp","streamId": unpackChannelInfo.streamId}); 330 let rtmpStream=this.mediaModule.getMediaPlayPath({"type":"rtmp","streamId": unpackChannelInfo.streamId});
  331 + let replay=this.mediaModule.getMediaRecordPlaybackPath({"type":"m3u8","streamId": unpackChannelInfo.streamId});
272 332
273 if(m3u8Stream.code==0){ 333 if(m3u8Stream.code==0){
274 receiveChannelInfo.m3u8Url=m3u8Stream.playUrl; 334 receiveChannelInfo.m3u8Url=m3u8Stream.playUrl;
@@ -276,21 +336,23 @@ class AudioApe extends Ape { @@ -276,21 +336,23 @@ class AudioApe extends Ape {
276 if(rtmpStream.code==0){ 336 if(rtmpStream.code==0){
277 receiveChannelInfo.rtmpUrl=rtmpStream.playUrl; 337 receiveChannelInfo.rtmpUrl=rtmpStream.playUrl;
278 } 338 }
279 - loger.log("AUDIO_PLAY");  
280 - console.log(receiveChannelInfo); 339 + if(replay.code==0){
  340 + receiveChannelInfo.replay=replay.playUrl;
  341 + }
  342 + loger.log("AUDIO_PLAY",receiveChannelInfo);
281 //广播播放视频的消息 343 //广播播放视频的消息
282 this._emit(MessageTypes.AUDIO_PLAY, receiveChannelInfo); 344 this._emit(MessageTypes.AUDIO_PLAY, receiveChannelInfo);
283 }else { 345 }else {
284 - loger.log("AUDIO_STOP");  
285 - console.log(receiveChannelInfo); 346 + loger.log("AUDIO_STOP",receiveChannelInfo);
286 //流已经停止 347 //流已经停止
287 this._emit(MessageTypes.AUDIO_STOP, receiveChannelInfo); 348 this._emit(MessageTypes.AUDIO_STOP, receiveChannelInfo);
288 } 349 }
289 }else { 350 }else {
290 loger.warn("消息是自己发送的或者是消息无效,不需要处理,消息内容如下:"); 351 loger.warn("消息是自己发送的或者是消息无效,不需要处理,消息内容如下:");
291 - console.log(unpackChannelInfo); 352 + loger.log(unpackChannelInfo);
292 353
293 } 354 }
  355 + this._emit(MessageTypes.AUDIO_UPDATE, unpackChannelInfo);
294 } 356 }
295 357
296 ///////数据的封包和解包///////////////////////////////////////// 358 ///////数据的封包和解包/////////////////////////////////////////
@@ -314,7 +376,7 @@ class AudioApe extends Ape { @@ -314,7 +376,7 @@ class AudioApe extends Ape {
314 packPduModel.timestamp =_param.timestamp||EngineUtils.creatTimestamp(); 376 packPduModel.timestamp =_param.timestamp||EngineUtils.creatTimestamp();
315 packPduModel.fromNodeId = GlobalConfig.nodeId; 377 packPduModel.fromNodeId = GlobalConfig.nodeId;
316 packPduModel.toNodeId = 0; 378 packPduModel.toNodeId = 0;
317 - console.log("packPdu",packPduModel); 379 + loger.log("packPdu",packPduModel);
318 return packPduModel; 380 return packPduModel;
319 } 381 }
320 382
@@ -326,7 +388,7 @@ class AudioApe extends Ape { @@ -326,7 +388,7 @@ class AudioApe extends Ape {
326 } 388 }
327 try { 389 try {
328 let packChannelInfo = pdu['RCAudioChannelInfoPdu'].decode(itemData); 390 let packChannelInfo = pdu['RCAudioChannelInfoPdu'].decode(itemData);
329 - console.log(packChannelInfo); 391 + loger.log(packChannelInfo);
330 return packChannelInfo; 392 return packChannelInfo;
331 } catch (err) { 393 } catch (err) {
332 loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message); 394 loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message);
@@ -65,11 +65,11 @@ class ChatApe extends Ape { @@ -65,11 +65,11 @@ class ChatApe extends Ape {
65 // if (!(chatSendPdu.isPublic || 0 === chatSendPdu.peer)) { 65 // if (!(chatSendPdu.isPublic || 0 === chatSendPdu.peer)) {
66 if (!chatSendPdu.isPublic && 0!=chatSendPdu.peer) { 66 if (!chatSendPdu.isPublic && 0!=chatSendPdu.peer) {
67 //发送给制定的人 67 //发送给制定的人
68 - loger.log('发送私聊消息.'); 68 + //loger.log('发送私聊消息.');
69 this.send(chatSendPdu); 69 this.send(chatSendPdu);
70 } else { 70 } else {
71 //发送给所有人 71 //发送给所有人
72 - loger.log('发送公聊消息.'); 72 + //loger.log('发送公聊消息.');
73 //this.sendUniform(chatSendPdu); 73 //this.sendUniform(chatSendPdu);
74 this.sendChatUniform(chatSendPdu); 74 this.sendChatUniform(chatSendPdu);
75 } 75 }
@@ -79,8 +79,8 @@ class ChatApe extends Ape { @@ -79,8 +79,8 @@ class ChatApe extends Ape {
79 var chatReceivePdu = pdu['RCChatSendDataRequestPdu'].decode(chatBuffer); 79 var chatReceivePdu = pdu['RCChatSendDataRequestPdu'].decode(chatBuffer);
80 80
81 var chatMsg = {}; 81 var chatMsg = {};
82 - chatMsg.fromNodeID = chatReceivePdu.initiator;  
83 - chatMsg.toNodeID = chatReceivePdu.peer; 82 + chatMsg.fromNodeId = chatReceivePdu.initiator;
  83 + chatMsg.toNodeId = chatReceivePdu.peer;
84 chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2); 84 chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
85 chatMsg.fromName = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.fromName, 2); 85 chatMsg.fromName = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.fromName, 2);
86 chatMsg.fromRole = chatReceivePdu.fromRole; 86 chatMsg.fromRole = chatReceivePdu.fromRole;
1 // ////////////////////////////////////////////////////////////////////////////// 1 // //////////////////////////////////////////////////////////////////////////////
2 -//会议控制APE 2 +//课堂控制APE
3 // ////////////////////////////////////////////////////////////////////////////// 3 // //////////////////////////////////////////////////////////////////////////////
4 4
5 import Ape from './Ape'; 5 import Ape from './Ape';
@@ -14,7 +14,7 @@ import EngineUtils from 'EngineUtils'; @@ -14,7 +14,7 @@ import EngineUtils from 'EngineUtils';
14 import TimerCounter from "TimerCounter"; 14 import TimerCounter from "TimerCounter";
15 15
16 let loger = Loger.getLoger('ConferApe'); 16 let loger = Loger.getLoger('ConferApe');
17 -let itemIdx=0;//table插入新数据的计数id,目前用时间戳 17 +let itemIdx = 0;//table插入新数据的计数id,目前用时间戳
18 18
19 class ConferApe extends Ape { 19 class ConferApe extends Ape {
20 constructor() { 20 constructor() {
@@ -23,7 +23,7 @@ class ConferApe extends Ape { @@ -23,7 +23,7 @@ class ConferApe extends Ape {
23 ApeConsts.CONFERENCE_SESSION_NAME, 23 ApeConsts.CONFERENCE_SESSION_NAME,
24 ApeConsts.CONFERENCE_SESSION_TAG 24 ApeConsts.CONFERENCE_SESSION_TAG
25 ); 25 );
26 - 26 + /*
27 // Attribures 27 // Attribures
28 this.hostNodeId = -1;//主持人的nodeId 28 this.hostNodeId = -1;//主持人的nodeId
29 // 用户的身份,5种类型: 29 // 用户的身份,5种类型:
@@ -34,8 +34,10 @@ class ConferApe extends Ape { @@ -34,8 +34,10 @@ class ConferApe extends Ape {
34 // record(暂时没用. 34 // record(暂时没用.
35 // 默认值: normal 35 // 默认值: normal
36 this.hostUserId = '';//主持人的 第三方userId 36 this.hostUserId = '';//主持人的 第三方userId
  37 + */
  38 +
37 this.rosters = {};//用户列表 39 this.rosters = {};//用户列表
38 - this.timerCounter=new TimerCounter();//计时器 40 + this.timerCounter = new TimerCounter();//计时器
39 41
40 // Ape Models 42 // Ape Models
41 this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer); 43 this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
@@ -54,21 +56,21 @@ class ConferApe extends Ape { @@ -54,21 +56,21 @@ class ConferApe extends Ape {
54 56
55 this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this)); 57 this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
56 58
57 - this.on(pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST, this.conferMsgComingHandler.bind(this));//这个是会议消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理  
58 - this.on(pdu.RCPDU_CONFERENCE_RECORD_REQUEST,this.onSendConferRecordRequestHandler.bind(this));//发送录制和停止录制消息 59 + this.on(pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST, this.conferMsgComingHandler.bind(this));//这个是课堂消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
  60 + this.on(pdu.RCPDU_CONFERENCE_RECORD_REQUEST, this.onSendConferRecordRequestHandler.bind(this));//发送录制和停止录制消息
59 } 61 }
60 62
61 - //加入会议 63 + //加入课堂
62 _joinSessionHandler(_data) { 64 _joinSessionHandler(_data) {
63 let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self; 65 let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
64 loger.log("_joinSessionHandler nodeInfoRecordPdu="); 66 loger.log("_joinSessionHandler nodeInfoRecordPdu=");
65 - console.log(nodeInfoRecordPdu); 67 + loger.log(nodeInfoRecordPdu);
66 let userDataPdu = new pdu['RCNodeInfoUserDataPdu']; 68 let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
67 userDataPdu.qq = ''; 69 userDataPdu.qq = '';
68 userDataPdu.skype = ''; 70 userDataPdu.skype = '';
69 71
70 nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer(); 72 nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
71 - nodeInfoRecordPdu.deviceType =GlobalConfig.deviceType;//设备类型 73 + nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType;//设备类型
72 74
73 let item = new pdu['RCRegistryRosterItemPdu']; 75 let item = new pdu['RCRegistryRosterItemPdu'];
74 item.nodeId = nodeInfoRecordPdu.nodeId; 76 item.nodeId = nodeInfoRecordPdu.nodeId;
@@ -95,17 +97,17 @@ class ConferApe extends Ape { @@ -95,17 +97,17 @@ class ConferApe extends Ape {
95 } 97 }
96 98
97 sendConferMsg(_messageInfo) { 99 sendConferMsg(_messageInfo) {
98 - if(this._classInfo==null||EngineUtils.isEmptyObject(this._classInfo)){  
99 - loger.log('不能发送会议消息.McuClient还未初始化数据!');  
100 - if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){  
101 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN); 100 + if (this._classInfo == null || EngineUtils.isEmptyObject(this._classInfo)) {
  101 + loger.log('不能发送课堂消息.McuClient还未初始化数据!');
  102 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  103 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
102 return; 104 return;
103 } 105 }
104 - return ; 106 + return;
105 } 107 }
106 108
107 // to, message 109 // to, message
108 - loger.log('发送会议消息.', _messageInfo); 110 + loger.log('发送课堂消息.', _messageInfo);
109 111
110 /* message RCConferenceSendDataRequestPdu { 112 /* message RCConferenceSendDataRequestPdu {
111 optional uint32 initiator = 1; 113 optional uint32 initiator = 1;
@@ -123,30 +125,30 @@ class ConferApe extends Ape { @@ -123,30 +125,30 @@ class ConferApe extends Ape {
123 conferSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message); 125 conferSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message);
124 //conferSendPdu.userData =UTF8.setBytesFromString(_messageInfo.message); 126 //conferSendPdu.userData =UTF8.setBytesFromString(_messageInfo.message);
125 conferSendPdu.isPublic = true; 127 conferSendPdu.isPublic = true;
126 - conferSendPdu.actionType=_messageInfo.actionType; 128 + conferSendPdu.actionType = _messageInfo.actionType;
127 // if (!(conferSendPdu.isPublic || 0 === conferSendPdu.peer)) { 129 // if (!(conferSendPdu.isPublic || 0 === conferSendPdu.peer)) {
128 - if (!conferSendPdu.isPublic && 0!=conferSendPdu.peer) { 130 + if (!conferSendPdu.isPublic && 0 != conferSendPdu.peer) {
129 //发送给制定的人 131 //发送给制定的人
130 - loger.log('发送私聊会议消息.'); 132 + loger.log('发送私聊课堂消息.');
131 this.send(conferSendPdu); 133 this.send(conferSendPdu);
132 } else { 134 } else {
133 //发送给所有人 135 //发送给所有人
134 - loger.log('发送公聊会议消息.'); 136 + loger.log('发送公聊课堂消息.');
135 this.sendChatUniform(conferSendPdu); 137 this.sendChatUniform(conferSendPdu);
136 } 138 }
137 } 139 }
138 140
139 //发送录制或停止录制的消息,{"recordStatus":true};true为开始录制,false为停止录制 141 //发送录制或停止录制的消息,{"recordStatus":true};true为开始录制,false为停止录制
140 sendConferRecordMsg(_param) { 142 sendConferRecordMsg(_param) {
141 - if(!this.mcu.connected){ 143 + if (!this.mcu.connected) {
142 loger.warn(GlobalConfig.getCurrentStatus()); 144 loger.warn(GlobalConfig.getCurrentStatus());
143 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; 145 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
144 } 146 }
145 // to, message 147 // to, message
146 loger.log('发送录制消息.', _param); 148 loger.log('发送录制消息.', _param);
147 149
148 - if(_param==null){  
149 - loger.warn("控制录制状的消息发送失败,参数错误",_param); 150 + if (_param == null) {
  151 + loger.warn("控制录制状的消息发送失败,参数错误", _param);
150 return; 152 return;
151 } 153 }
152 154
@@ -158,7 +160,7 @@ class ConferApe extends Ape { @@ -158,7 +160,7 @@ class ConferApe extends Ape {
158 }*/ 160 }*/
159 161
160 //保存当前的录制状态 162 //保存当前的录制状态
161 - GlobalConfig.recordStatus=_param.recordStatus||false; 163 + GlobalConfig.recordStatus = _param.recordStatus || false;
162 164
163 let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu']; 165 let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu'];
164 conferRecordSendPdu.type = pdu.RCPDU_CONFERENCE_RECORD_REQUEST; 166 conferRecordSendPdu.type = pdu.RCPDU_CONFERENCE_RECORD_REQUEST;
@@ -166,38 +168,44 @@ class ConferApe extends Ape { @@ -166,38 +168,44 @@ class ConferApe extends Ape {
166 conferRecordSendPdu.isPublic = true; 168 conferRecordSendPdu.isPublic = true;
167 169
168 conferRecordSendPdu.initiator = this._classInfo.nodeId;//发起人 170 conferRecordSendPdu.initiator = this._classInfo.nodeId;//发起人
169 - conferRecordSendPdu.record =GlobalConfig.recordStatus;  
170 - conferRecordSendPdu.classTime=GlobalConfig.classTimestamp;  
171 - conferRecordSendPdu.filename=GlobalConfig.recordFileName||GlobalConfig.classId+"_"+EngineUtils.creatTimestampYMD()+".rec"; 171 + conferRecordSendPdu.record = GlobalConfig.recordStatus;
  172 + conferRecordSendPdu.classTime = GlobalConfig.classTimestamp;
  173 + conferRecordSendPdu.filename = GlobalConfig.recordFileName || GlobalConfig.classId + "_" + EngineUtils.creatTimestampYMD() + ".rec";
172 this.sendChatUniform(conferRecordSendPdu); 174 this.sendChatUniform(conferRecordSendPdu);
173 } 175 }
174 176
175 //开启录制 177 //开启录制
176 - startRecord(){  
177 - loger.log('startRecord',"isHost",GlobalConfig.isHost,"recordStatus",GlobalConfig.recordStatus); 178 + startRecord() {
  179 + //如果录制的时间长超出设定的最大录制时间就不再录制
  180 + if(GlobalConfig.classTimestamp>=GlobalConfig.allowRecordMaxTime){
  181 + loger.warn('不能再录制,录制时间已经达到最大限制',GlobalConfig.classTimestamp);
  182 + return;
  183 + }
  184 +
  185 + loger.log('startRecord', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
178 //如果是host 186 //如果是host
179 - if(GlobalConfig.isHost){  
180 - GlobalConfig.classStopTime=EngineUtils.creatTimestampStr();  
181 - this.sendConferRecordMsg({"recordStatus":true}); 187 + if (GlobalConfig.isHost) {
  188 + GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
  189 + this.sendConferRecordMsg({"recordStatus": true});
182 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 190 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
183 - this._emit(MessageTypes.CLASS_RECORD_START);//会议开始录制 191 + this._emit(MessageTypes.CLASS_RECORD_START);//课堂开始录制
184 } 192 }
185 } 193 }
186 194
187 //停止录制 195 //停止录制
188 - stopRecord(){  
189 - loger.log('stopRecord',"isHost",GlobalConfig.isHost,"recordStatus",GlobalConfig.recordStatus); 196 + stopRecord() {
  197 + loger.log('stopRecord', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
190 //如果是host,并且当前正在录制中 198 //如果是host,并且当前正在录制中
191 - if(GlobalConfig.isHost&&GlobalConfig.recordStatus){  
192 - GlobalConfig.classStopTime=EngineUtils.creatTimestampStr();  
193 - this.sendConferRecordMsg({"recordStatus":false}); 199 + if (GlobalConfig.isHost && GlobalConfig.recordStatus) {
  200 + GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
  201 + this.sendConferRecordMsg({"recordStatus": false});
194 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 202 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
195 } 203 }
196 } 204 }
197 205
198 206
199 - //主动离开会议,发送通知到服务器  
200 - leaveClass(){ 207 + //主动离开课堂,发送通知到服务器
  208 + leaveClass() {
201 let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self; 209 let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
202 let userDataPdu = new pdu['RCNodeInfoUserDataPdu']; 210 let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
203 userDataPdu.qq = ''; 211 userDataPdu.qq = '';
@@ -212,7 +220,7 @@ class ConferApe extends Ape { @@ -212,7 +220,7 @@ class ConferApe extends Ape {
212 220
213 let rosterUpdateItem = new pdu['RCRegistryRosterDeleteItemPdu']; 221 let rosterUpdateItem = new pdu['RCRegistryRosterDeleteItemPdu'];
214 rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_DELETE_PDU; 222 rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_DELETE_PDU;
215 - rosterUpdateItem.nodeId=GlobalConfig.nodeId; 223 + rosterUpdateItem.nodeId = GlobalConfig.nodeId;
216 224
217 let updateObjPdu = new pdu['RCRegistryUpdateObjPdu']; 225 let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
218 updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID; 226 updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
@@ -231,66 +239,68 @@ class ConferApe extends Ape { @@ -231,66 +239,68 @@ class ConferApe extends Ape {
231 } 239 }
232 240
233 //还原课堂状态 241 //还原课堂状态
234 - restorClass(){  
235 - GlobalConfig.classTimestamp=0;  
236 - GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_WAIT;  
237 - GlobalConfig.classStopTime=EngineUtils.creatTimestampStr(); 242 + restorClass() {
  243 + GlobalConfig.classTimestamp = 0;
  244 + GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_WAIT;
  245 + GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
238 this.stopRecord(); 246 this.stopRecord();
239 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 247 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
240 - this.sendUpdaterClassStatusInfo({"actionType":0}); 248 + this.sendUpdaterClassStatusInfo({"actionType": 0});
241 loger.log('restorClass'); 249 loger.log('restorClass');
242 } 250 }
243 251
244 //开始上课 252 //开始上课
245 - startClass(_param){  
246 - if(GlobalConfig.isHost){ 253 + startClass(_param) {
  254 + if (GlobalConfig.isHost) {
247 255
248 - let timestamp=EngineUtils.creatTimestampStr();  
249 - GlobalConfig.classStopTime=timestamp; 256 + let timestamp = EngineUtils.creatTimestampStr();
  257 + GlobalConfig.classStopTime = timestamp;
250 258
251 //如果录制的文件名不存在,需要创建一个名字 259 //如果录制的文件名不存在,需要创建一个名字
252 - let timestampYMD=EngineUtils.creatTimestampYMD();  
253 - GlobalConfig.recordFileName=GlobalConfig.recordFileName||  
254 - GlobalConfig.siteId+"/"+timestampYMD+"/"  
255 - +GlobalConfig.classId+"_"+timestampYMD+".rec";//4、文件名称 $RECORD_HOME/`site id`/`日期`/`filename` 例:/data/record/su/20161216/`filename` 260 + let timestampYMD = EngineUtils.creatTimestampYMD();
  261 + GlobalConfig.recordFileName = GlobalConfig.recordFileName ||
  262 + GlobalConfig.siteId + "/" + timestampYMD + "/"
  263 + + GlobalConfig.classId + "_" + timestampYMD + ".rec";//4、文件名称 $RECORD_HOME/`site id`/`日期`/`filename` 例:/data/record/su/20161216/`filename`
256 264
257 - if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_WAIT){ 265 + if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
258 //之前是为开始状态,第一次点开始 266 //之前是为开始状态,第一次点开始
259 - GlobalConfig.classStartTime=timestamp; 267 + GlobalConfig.classStartTime = timestamp;
260 } 268 }
261 269
262 - GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_STARTED; 270 + GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_STARTED;
263 //开始录制 271 //开始录制
264 this.startRecord(); 272 this.startRecord();
265 - //会议状态改变 273 + //课堂状态改变
266 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 274 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
267 - //同步会议状态  
268 - this.sendUpdaterClassStatusInfo({"actionType":1}); 275 + //同步课堂状态
  276 + this.sendUpdaterClassStatusInfo({"actionType": 1});
269 277
270 //开始计时 278 //开始计时
271 this.startTimerCounter(); 279 this.startTimerCounter();
272 - }else { 280 + } else {
273 loger.warn('没有权限'); 281 loger.warn('没有权限');
274 } 282 }
275 } 283 }
  284 +
276 //暂停上课 285 //暂停上课
277 - pauseClass(_param){  
278 - if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_WAIT){ 286 + pauseClass(_param) {
  287 + if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
279 loger.warn('还没有开始,不能点暂停'); 288 loger.warn('还没有开始,不能点暂停');
280 return; 289 return;
281 } 290 }
282 291
283 - GlobalConfig.classStatus=ApeConsts.CLASS_STATUS_PAUSE;  
284 - GlobalConfig.classStopTime=EngineUtils.creatTimestampStr(); 292 + GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_PAUSE;
  293 + GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
285 294
286 this.stopRecord(); 295 this.stopRecord();
287 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 296 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
288 - this.sendUpdaterClassStatusInfo({"actionType":2}); 297 + this.sendUpdaterClassStatusInfo({"actionType": 2});
289 this.stopTimerCounter(); 298 this.stopTimerCounter();
290 } 299 }
  300 +
291 //关闭课堂 301 //关闭课堂
292 - closeClass(_param){  
293 - if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_WAIT){ 302 + closeClass(_param) {
  303 + if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
294 loger.warn('还没有开始,不能点关闭'); 304 loger.warn('还没有开始,不能点关闭');
295 return; 305 return;
296 } 306 }
@@ -298,34 +308,34 @@ class ConferApe extends Ape { @@ -298,34 +308,34 @@ class ConferApe extends Ape {
298 this.stopTimerCounter(); 308 this.stopTimerCounter();
299 this.restorClass(); 309 this.restorClass();
300 //把所有人都踢出课堂 310 //把所有人都踢出课堂
301 - this.sendConferMsg({"to":0,"message":"所有人退出会议","actionType":ApeConsts.CLASS_ACTION_CLOSE_ALL}); 311 + this.sendConferMsg({"to": 0, "message": "所有人退出课堂", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL});
302 } 312 }
303 313
304 314
305 - //更新会议信息  
306 - sendUpdaterClassStatusInfo(_param){ 315 + //更新课堂信息
  316 + sendUpdaterClassStatusInfo(_param) {
307 loger.log('sendUpdaterClassStatusInfo'); 317 loger.log('sendUpdaterClassStatusInfo');
308 - if(_param==null||EngineUtils.isEmptyObject(_param)){ 318 + if (_param == null || EngineUtils.isEmptyObject(_param)) {
309 loger.log('sendUpdaterClassStatusInfo,参数错误'); 319 loger.log('sendUpdaterClassStatusInfo,参数错误');
310 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);  
311 - return ; 320 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
  321 + return;
312 } 322 }
313 - itemIdx=ApeConsts.CONFERENCE_OBJ_TABLE_ID;// itemIdx=_param.itemIdx;  
314 - let modelPdu = this.packPdu(_param,itemIdx); 323 + itemIdx = ApeConsts.CONFERENCE_OBJ_TABLE_ID;// itemIdx=_param.itemIdx;
  324 + let modelPdu = this.packPdu(_param, itemIdx);
315 //loger.log('sendUpdaterClassStatusInfo----2------'); 325 //loger.log('sendUpdaterClassStatusInfo----2------');
316 - console.log(modelPdu); 326 + loger.log(modelPdu);
317 327
318 - if(modelPdu==null){ 328 + if (modelPdu == null) {
319 loger.log('sendUpdaterClassStatusInfo,参数错误'); 329 loger.log('sendUpdaterClassStatusInfo,参数错误');
320 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);  
321 - return ; 330 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
  331 + return;
322 } 332 }
323 333
324 let tableItemPdu = new pdu['RCRegistryTableItemPdu']; 334 let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
325 - tableItemPdu.itemIdx=itemIdx; 335 + tableItemPdu.itemIdx = itemIdx;
326 tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定 336 tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定
327 - tableItemPdu.registerObjId=ApeConsts.CONFERENCE_OBJ_TABLE_ID;  
328 - tableItemPdu.itemData =modelPdu.toArrayBuffer(); 337 + tableItemPdu.registerObjId = ApeConsts.CONFERENCE_OBJ_TABLE_ID;
  338 + tableItemPdu.itemData = modelPdu.toArrayBuffer();
329 339
330 340
331 //updater 341 //updater
@@ -350,18 +360,18 @@ class ConferApe extends Ape { @@ -350,18 +360,18 @@ class ConferApe extends Ape {
350 adapterPdu.type = pdu.RCPDU_REG_ADAPTER; 360 adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
351 adapterPdu.item.push(adapterItemPdu); 361 adapterPdu.item.push(adapterItemPdu);
352 362
353 - console.log("会议发送更新数据============");  
354 - this.sendUniform(adapterPdu,true); 363 + loger.log("课堂发送更新数据============");
  364 + this.sendUniform(adapterPdu, true);
355 } 365 }
356 366
357 367
358 /////收到消息处理///////////////////////////////////////////////////////////////////////////////// 368 /////收到消息处理/////////////////////////////////////////////////////////////////////////////////
359 //加入channel成功 369 //加入channel成功
360 - onJoinChannelHandlerSuccess(){  
361 - loger.log('ConferApe.onJoinChannelHandlerSuccess',GlobalConfig.classStatus);  
362 - this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this),1);  
363 - //如果当前会议正在进行中,开启计时器  
364 - if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_STARTED){ 370 + onJoinChannelHandlerSuccess() {
  371 + loger.log('ConferApe.onJoinChannelHandlerSuccess', GlobalConfig.classStatus);
  372 + this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1);
  373 + //如果当前课堂正在进行中,开启计时器
  374 + if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
365 //开始计时 375 //开始计时
366 this.startTimerCounter(); 376 this.startTimerCounter();
367 377
@@ -369,69 +379,72 @@ class ConferApe extends Ape { @@ -369,69 +379,72 @@ class ConferApe extends Ape {
369 this.startRecord(); 379 this.startRecord();
370 } 380 }
371 } 381 }
  382 +
372 //开启计时器 383 //开启计时器
373 - startTimerCounter(){ 384 + startTimerCounter() {
374 this.timerCounter.startTimer(); 385 this.timerCounter.startTimer();
375 } 386 }
  387 +
376 //停止计时器 388 //停止计时器
377 - stopTimerCounter(){ 389 + stopTimerCounter() {
378 this.timerCounter.stopTimer(); 390 this.timerCounter.stopTimer();
379 } 391 }
380 - timerCounterUptate(){  
381 - if(!this.mcu.connected){ 392 +
  393 + timerCounterUptate() {
  394 + if (!this.mcu.connected) {
382 loger.warn('MCU 连接已经断开'); 395 loger.warn('MCU 连接已经断开');
383 this.stopTimerCounter(); 396 this.stopTimerCounter();
384 } 397 }
385 //如果还没开始或已经暂停、关闭,不做计时处理 398 //如果还没开始或已经暂停、关闭,不做计时处理
386 - if(GlobalConfig.classStatus!=ApeConsts.CLASS_STATUS_STARTED){  
387 - loger.warn('当前课堂已经暂停或者未开始,不计时',"classStatus-->",GlobalConfig.classStatus); 399 + if (GlobalConfig.classStatus != ApeConsts.CLASS_STATUS_STARTED) {
  400 + loger.warn('当前课堂已经暂停或者未开始,不计时', "classStatus-->", GlobalConfig.classStatus);
388 return; 401 return;
389 } 402 }
390 - GlobalConfig.classTimestamp=GlobalConfig.classTimestamp+1;//计时 403 + GlobalConfig.classTimestamp = GlobalConfig.classTimestamp + 1;//计时
391 //loger.log('课堂进行时间',GlobalConfig.classTimestamp); 404 //loger.log('课堂进行时间',GlobalConfig.classTimestamp);
392 - this._emit(MessageTypes.CLASS_UPDATE_TIMER,{"classTimestamp":GlobalConfig.classTimestamp}); 405 + this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": GlobalConfig.classTimestamp});
393 406
394 - if(GlobalConfig.classTimestamp%GlobalConfig.updateClassInfoDelay==0){ 407 + if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
395 //如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器 408 //如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
396 - if(GlobalConfig.isHost){ 409 + if (GlobalConfig.isHost) {
397 //保存数据到Sass 410 //保存数据到Sass
398 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 411 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
399 412
400 //同步消息给其他人 413 //同步消息给其他人
401 - this.sendUpdaterClassStatusInfo({"actionType":1}); 414 + this.sendUpdaterClassStatusInfo({"actionType": 1});
402 } 415 }
403 } 416 }
404 } 417 }
405 418
406 tableUpdateHandler(owner, itemIdx, itemData) { 419 tableUpdateHandler(owner, itemIdx, itemData) {
407 try { 420 try {
408 - let model=this.unPackPdu(owner, itemIdx,itemData); 421 + let model = this.unPackPdu(owner, itemIdx, itemData);
409 loger.log('tableUpdateHandler'); 422 loger.log('tableUpdateHandler');
410 - console.log(model); 423 + loger.log(model);
411 424
412 - //处理会议更新的信息  
413 - if(model&&model.classStatusInfo){ 425 + //处理课堂更新的信息
  426 + if (model && model.classStatusInfo) {
414 GlobalConfig.setClassStatusInfo(model.classStatusInfo); 427 GlobalConfig.setClassStatusInfo(model.classStatusInfo);
415 } 428 }
416 - //通知应用层更新会议状态  
417 - this._emit(MessageTypes.CLASS_UPTATE_STATUS,GlobalConfig.classStatusInfo); 429 + //通知应用层更新课堂状态
  430 + this._emit(MessageTypes.CLASS_UPTATE_STATUS, GlobalConfig.classStatusInfo);
418 431
419 //如果MCU已经断开连接,停止计时器 432 //如果MCU已经断开连接,停止计时器
420 - if(!this.mcu.connected){ 433 + if (!this.mcu.connected) {
421 //停止计时 434 //停止计时
422 this.stopTimerCounter(); 435 this.stopTimerCounter();
423 return; 436 return;
424 } 437 }
425 438
426 - if(GlobalConfig.classStatus==ApeConsts.CLASS_STATUS_STARTED){  
427 - //如果会议在进行中,开始计时器 439 + if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
  440 + //如果课堂在进行中,开始计时器
428 this.startTimerCounter(); 441 this.startTimerCounter();
429 - }else { 442 + } else {
430 //停止计时 443 //停止计时
431 this.stopTimerCounter(); 444 this.stopTimerCounter();
432 } 445 }
433 } catch (e) { 446 } catch (e) {
434 - loger.warn('ConferApe table update got exception. itemIdx',itemIdx); 447 + loger.warn('ConferApe table update got exception. itemIdx', itemIdx);
435 } 448 }
436 } 449 }
437 450
@@ -448,12 +461,12 @@ class ConferApe extends Ape { @@ -448,12 +461,12 @@ class ConferApe extends Ape {
448 chatMsg.fromNodeID = chatReceivePdu.initiator; 461 chatMsg.fromNodeID = chatReceivePdu.initiator;
449 chatMsg.toNodeID = chatReceivePdu.peer; 462 chatMsg.toNodeID = chatReceivePdu.peer;
450 chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2); 463 chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
451 - chatMsg.actionType=chatReceivePdu.actionType;  
452 - loger.log("conferMsgComingHandler",chatMsg);  
453 - switch (chatMsg.actionType){ 464 + chatMsg.actionType = chatReceivePdu.actionType;
  465 + loger.log("conferMsgComingHandler", chatMsg);
  466 + switch (chatMsg.actionType) {
454 case ApeConsts.CLASS_ACTION_CLOSE_ALL: 467 case ApeConsts.CLASS_ACTION_CLOSE_ALL:
455 loger.log(chatMsg.message); 468 loger.log(chatMsg.message);
456 - //会议关闭,所有人都退出 469 + //收到课堂关闭,所有人都退出,执行自己关闭的流程
457 this._emit(MessageTypes.CLASS_EXIT); 470 this._emit(MessageTypes.CLASS_EXIT);
458 break; 471 break;
459 default: 472 default:
@@ -461,88 +474,124 @@ class ConferApe extends Ape { @@ -461,88 +474,124 @@ class ConferApe extends Ape {
461 } 474 }
462 } 475 }
463 476
464 - onSendConferRecordRequestHandler(_data){ 477 + onSendConferRecordRequestHandler(_data) {
465 loger.log("onSendConferRecordRequestHandler"); 478 loger.log("onSendConferRecordRequestHandler");
466 - try{  
467 - let conferRecordSendPdu =pdu['RCConferenceRecordRequestPdu'].decode(_data);  
468 - console.log(conferRecordSendPdu);  
469 - }catch (err){  
470 - loger.warn("onSendConferRecordRequestHandler err",err.message); 479 + try {
  480 + let conferRecordSendPdu = pdu['RCConferenceRecordRequestPdu'].decode(_data);
  481 + loger.log(conferRecordSendPdu);
  482 + } catch (err) {
  483 + loger.warn("onSendConferRecordRequestHandler err", err.message);
471 } 484 }
472 485
473 } 486 }
474 487
475 rosterInsertHandler(nodeId, nodeData) { 488 rosterInsertHandler(nodeId, nodeData) {
476 - if(GlobalConfig.nodeId==nodeId){  
477 - loger.log("自己加入 rosterInsertHandler");  
478 - }else {  
479 - loger.log("有人加入 rosterInsertHandler"); 489 + if (GlobalConfig.nodeId == nodeId) {
  490 + // loger.log("自己加入 rosterInsertHandler");
  491 + } else {
  492 + // loger.log("有人加入 rosterInsertHandler");
480 this.rosterUpdateHandler(nodeId, nodeData); 493 this.rosterUpdateHandler(nodeId, nodeData);
481 } 494 }
482 } 495 }
483 496
484 //更新人员列表数据 497 //更新人员列表数据
485 rosterUpdateHandler(nodeId, nodeData) { 498 rosterUpdateHandler(nodeId, nodeData) {
486 - if (nodeData.role === ApeConsts.NR_MASTER ||  
487 - nodeData.role === ApeConsts.NR_SLAVE) {  
488 - this.hostNodeId = nodeData.nodeId;  
489 - this.hostUserId = nodeData.userId; 499 + //如果是自己的信息,不处理跳过
  500 + if (nodeId == GlobalConfig.nodeId) {
  501 + loger.log("自己加入课堂的消息,不需要处理");
  502 + this.rosters[nodeId] = nodeData;
  503 + return;
490 } 504 }
491 - if (nodeData.role === ApeConsts.NR_NORMAL &&  
492 - this.hostNodeId === nodeData.nodeId) {  
493 - this.hostNodeId = -1;  
494 - this.hostUserId = ''; 505 +
  506 + loger.log(nodeId, "加入课堂,role-->", nodeData.role, ApeConsts.userTypes[nodeData.role]);
  507 +
  508 + //新加入的人员不是自己
  509 + //1.判断进入的用户身份,如果进入的人身份是host,助教,监课,并且和自己的身份冲突,自己会被踢掉
  510 + //2.最后进入的人会踢掉之前进入的人,nodeId是按时间戳生成的,最后进入的人nodeId的值比之前进入的人大
  511 + if (parseInt(nodeId) > GlobalConfig.nodeId) {
  512 + if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) {
  513 + this.kickOutRoster();
  514 + return;
  515 + } else if (nodeData.role == ApeConsts.NR_PRESENTER && GlobalConfig.isPresenter) {
  516 + this.kickOutRoster();
  517 + return;
  518 + } else if (nodeData.role == ApeConsts.NR_ASSISTANT && GlobalConfig.isAssistant) {
  519 + this.kickOutRoster();
  520 + return;
  521 + } else if (nodeData.role == ApeConsts.NR_INVISIBLE && GlobalConfig.isInvisible) {
  522 + this.kickOutRoster();
  523 + return;
495 } 524 }
  525 + }
  526 +
  527 +
  528 + //处理用户信息
496 let rosterExists = this.rosters[nodeId]; 529 let rosterExists = this.rosters[nodeId];
497 this.rosters[nodeId] = nodeData; 530 this.rosters[nodeId] = nodeData;
498 - let userDataObj=null; 531 + let userDataObj = null;
499 if (!rosterExists) { 532 if (!rosterExists) {
500 - try{  
501 - userDataObj=pdu['RCNodeInfoUserDataPdu'].decode(nodeData.userData);  
502 - }catch (err){  
503 - loger.log("RCNodeInfoUserDataPdu decode err",err.message); 533 + try {
  534 + userDataObj = pdu['RCNodeInfoUserDataPdu'].decode(nodeData.userData);
  535 + } catch (err) {
  536 + loger.log("RCNodeInfoUserDataPdu decode err", err.message);
504 } 537 }
505 538
506 - let newNodeData=nodeData;  
507 - newNodeData.userData=userDataObj;  
508 - loger.log("更新人员列表数据 rosterUpdateHandler",{"nodeId":nodeId});  
509 - this._emit(MessageTypes.CLASS_INSERT_ROSTER, {"nodeId":nodeId,"nodeData":newNodeData}); 539 + let newNodeData = nodeData;
  540 + newNodeData.userData = userDataObj;
  541 +
  542 + //如果是监课,不告诉其他人
  543 + if (nodeData.role == ApeConsts.NR_INVISIBLE) {
  544 + loger.log("NR_INVISIBLE");
  545 + return;
  546 + }
  547 +
  548 + this._emit(MessageTypes.CLASS_INSERT_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData});
510 this.emitRosterChange(); 549 this.emitRosterChange();
511 - }else { 550 +
  551 + } else {
512 //loger.log("更新人员列表数据,rosterExists已经存在",rosterExists); 552 //loger.log("更新人员列表数据,rosterExists已经存在",rosterExists);
513 } 553 }
514 } 554 }
515 555
516 - //视频模块发生更新,人员状态需要更新  
517 - updaterRosterStatus(_param){  
518 - if(_param){  
519 - loger.log("媒体模块发生更新,人员状态需要更新,fromNodeId->",_param.fromNodeId);  
520 - loger.log(_param.status,_param.fromNodeId);  
521 - //console.log(_param.fromNodeId);  
522 - //如果是自己。改变自己的状态同步到MCU  
523 - //if(_param.fromNodeId==GlobalConfig.nodeId){  
524 - //  
525 - //}  
526 - 556 + //踢出用户
  557 + kickOutRoster() {
  558 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_KICK_OUT);
  559 + this._emit(MessageTypes.CLASS_EXIT);
  560 + }
527 561
  562 + //视频模块发生更新,人员状态需要更新
  563 + updaterRosterStatus(_param) {
  564 + //loger.log("媒体模块发生更新,人员状态需要更新,fromNodeId->",_param.fromNodeId);
528 //如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的 565 //如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的
529 - if(_param.status==ApeConsts.CHANNEL_STATUS_OPENING&&this.rosters[_param.fromNodeId]==null){  
530 - loger.log("媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->",_param);  
531 - this._emit(MessageTypes.CLASS_NONENTITY_ROSTER,{"nodeId":_param.fromNodeId});  
532 - } 566 + if (_param && _param.status == ApeConsts.CHANNEL_STATUS_OPENING && this.rosters[_param.fromNodeId] == null) {
  567 + loger.log("媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->", _param);
  568 + this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": _param.fromNodeId});
533 } 569 }
534 } 570 }
  571 +
535 //删除用户 572 //删除用户
536 rosterDelHandler(nodeId) { 573 rosterDelHandler(nodeId) {
537 - if(GlobalConfig.nodeId==nodeId){  
538 - loger.log("自己离开 rosterDelHandler"); 574 + if (GlobalConfig.nodeId == nodeId) {
  575 + loger.log("自己离开课堂");
539 // 自己退出 576 // 自己退出
540 this._emit(MessageTypes.CLASS_EXIT); 577 this._emit(MessageTypes.CLASS_EXIT);
541 - }else {  
542 - loger.log("有人离开 rosterDelHandler"); 578 + } else {
  579 + loger.log(nodeId, "离开课堂");
543 delete this.rosters[nodeId]; 580 delete this.rosters[nodeId];
544 - this._emit(MessageTypes.CLASS_DELETE_ROSTER, {"nodeId":nodeId});  
545 this.emitRosterChange(); 581 this.emitRosterChange();
  582 + this._emit(MessageTypes.CLASS_DELETE_ROSTER, {"nodeId": nodeId});
  583 +
  584 + //当前人员列表中抽一个人来检查离开人员是否占用频道
  585 + for (let key in this.rosters) {
  586 + let randNodeId = parseInt(key);
  587 + if (randNodeId == GlobalConfig.nodeId) {
  588 + loger.log(randNodeId, "有权限检查离开的人员是否占用channel");
  589 + this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": nodeId});
  590 + } else {
  591 + loger.warn(GlobalConfig.nodeId, "没有权限检查离开的人员是否占用channel");
  592 + }
  593 + return;
  594 + }
546 } 595 }
547 } 596 }
548 597
@@ -552,36 +601,36 @@ class ConferApe extends Ape { @@ -552,36 +601,36 @@ class ConferApe extends Ape {
552 } 601 }
553 602
554 ///////数据的封包和解包///////////////////////////////////////// 603 ///////数据的封包和解包/////////////////////////////////////////
555 - packPdu(_param,_itemIdx){  
556 - loger.log("会议===packPdu "); 604 + packPdu(_param, _itemIdx) {
  605 + loger.log("课堂===packPdu ");
557 //验证坐标点集合数组是否合法 606 //验证坐标点集合数组是否合法
558 - if(_param==null||_itemIdx==null){  
559 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 607 + if (_param == null || _itemIdx == null) {
  608 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
560 return null; 609 return null;
561 } 610 }
562 - let classStatusInfo=new pdu['RCClassStatusInfoPdu'];  
563 - classStatusInfo.nodeId=GlobalConfig.nodeId;//mcu中的唯一ID  
564 - classStatusInfo.userId=GlobalConfig.userId;  
565 - classStatusInfo.userName=GlobalConfig.userName;  
566 - classStatusInfo.siteId=GlobalConfig.siteId;//站点号  
567 - classStatusInfo.classId=GlobalConfig.classId;  
568 - classStatusInfo.className=GlobalConfig.className;  
569 - classStatusInfo.classType=GlobalConfig.classType;//课堂类型  
570 - classStatusInfo.classStatus=GlobalConfig.classStatus;//课堂的状态  
571 - classStatusInfo.classStartTime=GlobalConfig.classStartTime;//课堂点击开始时间  
572 - classStatusInfo.classStopTime=GlobalConfig.classStopTime;//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳  
573 - classStatusInfo.classTimestamp=GlobalConfig.classTimestamp;//相对于点开始课堂的时间戳  
574 - classStatusInfo.classBeginTime=GlobalConfig.classBeginTime;//课堂创建的时间,这个是Sass返回的  
575 - classStatusInfo.classEndTime=GlobalConfig.classEndTime;//课堂结束的时间,这个是Sass返回的  
576 - classStatusInfo.recordStatus=GlobalConfig.recordStatus;//当前录制状态  
577 - classStatusInfo.recordTimestamp=GlobalConfig.recordTimestamp;//相对于首次开始录制的时间戳  
578 - classStatusInfo.recordFileName=GlobalConfig.recordFileName;//录制的文件名  
579 - classStatusInfo.recordDownloadUrl=GlobalConfig.recordDownloadUrl;//下载地址  
580 - classStatusInfo.serverTimestamp=GlobalConfig.serverTimestamp;//当前的系统时间戳  
581 - classStatusInfo.activeDocId=GlobalConfig.activeDocId;//当前激活的文档id  
582 - classStatusInfo.activeDocCurPage=GlobalConfig.activeDocCurPage;//当前激活的文档的当前页  
583 -  
584 - loger.log("classStatusInfo-------------",classStatusInfo); 611 + let classStatusInfo = new pdu['RCClassStatusInfoPdu'];
  612 + classStatusInfo.nodeId = GlobalConfig.nodeId;//mcu中的唯一ID
  613 + classStatusInfo.userId = GlobalConfig.userId;
  614 + classStatusInfo.userName = GlobalConfig.userName;
  615 + classStatusInfo.siteId = GlobalConfig.siteId;//站点号
  616 + classStatusInfo.classId = GlobalConfig.classId;
  617 + classStatusInfo.className = GlobalConfig.className;
  618 + classStatusInfo.classType = GlobalConfig.classType;//课堂类型
  619 + classStatusInfo.classStatus = GlobalConfig.classStatus;//课堂的状态
  620 + classStatusInfo.classStartTime = GlobalConfig.classStartTime;//课堂点击开始时间
  621 + classStatusInfo.classStopTime = GlobalConfig.classStopTime;//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
  622 + classStatusInfo.classTimestamp = GlobalConfig.classTimestamp;//相对于点开始课堂的时间戳
  623 + classStatusInfo.classBeginTime = GlobalConfig.classBeginTime;//课堂创建的时间,这个是Sass返回的
  624 + classStatusInfo.classEndTime = GlobalConfig.classEndTime;//课堂结束的时间,这个是Sass返回的
  625 + classStatusInfo.recordStatus = GlobalConfig.recordStatus;//当前录制状态
  626 + classStatusInfo.recordTimestamp = GlobalConfig.recordTimestamp;//相对于首次开始录制的时间戳
  627 + classStatusInfo.recordFileName = GlobalConfig.recordFileName;//录制的文件名
  628 + classStatusInfo.recordDownloadUrl = GlobalConfig.recordDownloadUrl;//下载地址
  629 + classStatusInfo.serverTimestamp = GlobalConfig.serverTimestamp;//当前的系统时间戳
  630 + classStatusInfo.activeDocId = GlobalConfig.activeDocId;//当前激活的文档id
  631 + classStatusInfo.activeDocCurPage = GlobalConfig.activeDocCurPage;//当前激活的文档的当前页
  632 +
  633 + loger.log("classStatusInfo-------------", classStatusInfo);
585 634
586 /* 635 /*
587 optional uint32 item_idx=1; 636 optional uint32 item_idx=1;
@@ -591,27 +640,27 @@ class ConferApe extends Ape { @@ -591,27 +640,27 @@ class ConferApe extends Ape {
591 optional RCClassStatusInfoPdu class_status_info=5;//当前课堂状态的信息 640 optional RCClassStatusInfoPdu class_status_info=5;//当前课堂状态的信息
592 */ 641 */
593 //判断type类型,根据type设置不同的参数 642 //判断type类型,根据type设置不同的参数
594 - let modelPdu =new pdu['RCClassSendDataModelPdu'];  
595 - modelPdu.itemIdx=_itemIdx;  
596 - modelPdu.from=GlobalConfig.nodeId;  
597 - modelPdu.owner=GlobalConfig.nodeId; 643 + let modelPdu = new pdu['RCClassSendDataModelPdu'];
  644 + modelPdu.itemIdx = _itemIdx;
  645 + modelPdu.from = GlobalConfig.nodeId;
  646 + modelPdu.owner = GlobalConfig.nodeId;
598 //modelPdu.actionType =_param.actionType; 647 //modelPdu.actionType =_param.actionType;
599 - modelPdu.classStatusInfo=classStatusInfo; 648 + modelPdu.classStatusInfo = classStatusInfo;
600 return modelPdu; 649 return modelPdu;
601 } 650 }
602 651
603 - unPackPdu(owner, itemIdx,itemData){  
604 - loger.log("会议===unPackPdu ");  
605 - if(owner==null||itemIdx==null||itemData==null){  
606 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 652 + unPackPdu(owner, itemIdx, itemData) {
  653 + loger.log("课堂===unPackPdu ");
  654 + if (owner == null || itemIdx == null || itemData == null) {
  655 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
607 return null; 656 return null;
608 } 657 }
609 658
610 - try{  
611 - let modelPdu= pdu['RCClassSendDataModelPdu'].decode(itemData); 659 + try {
  660 + let modelPdu = pdu['RCClassSendDataModelPdu'].decode(itemData);
612 return modelPdu; 661 return modelPdu;
613 - }catch (err){  
614 - loger.log("会议收到数据 unPackPdu Pdu解析错误,itemIdx="+itemIdx+" err:"+err.message); 662 + } catch (err) {
  663 + loger.log("课堂收到数据 unPackPdu Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message);
615 } 664 }
616 return null; 665 return null;
617 } 666 }
@@ -35,7 +35,7 @@ class DocApe extends Ape { @@ -35,7 +35,7 @@ class DocApe extends Ape {
35 //this.activeDocItemIdx =0;//当前激活的文档itemIdx 35 //this.activeDocItemIdx =0;//当前激活的文档itemIdx
36 //this.activeDocCurPage=1;//当前激活的文档的当前页 36 //this.activeDocCurPage=1;//当前激活的文档的当前页
37 // 延迟 37 // 延迟
38 - this._apeDelayed = true; 38 + this._apeDelayed = false;
39 39
40 // Ape Models 40 // Ape Models
41 this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer); 41 this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
@@ -212,7 +212,7 @@ class DocApe extends Ape { @@ -212,7 +212,7 @@ class DocApe extends Ape {
212 //切换文档 212 //切换文档
213 documentSwitchDoc(paramInfo){ 213 documentSwitchDoc(paramInfo){
214 loger.log('切换文档,documentSwitchDoc'); 214 loger.log('切换文档,documentSwitchDoc');
215 - console.log(paramInfo); 215 + loger.log(paramInfo);
216 if(paramInfo==null||paramInfo.itemIdx==null){ 216 if(paramInfo==null||paramInfo.itemIdx==null){
217 loger.warn('documentSwitch失败,参数错误',paramInfo); 217 loger.warn('documentSwitch失败,参数错误',paramInfo);
218 this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 218 this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
@@ -246,8 +246,8 @@ class DocApe extends Ape { @@ -246,8 +246,8 @@ class DocApe extends Ape {
246 docDataModel.action=ApeConsts.DOC_ACTION_SWITCH_DOC; 246 docDataModel.action=ApeConsts.DOC_ACTION_SWITCH_DOC;
247 docDataModel.visible=paramInfo.visible||false;//默认是false 247 docDataModel.visible=paramInfo.visible||false;//默认是false
248 248
249 - loger.log('切换文档,当前文档和上一个显示的文档都需要更新状态');  
250 - console.log({"oldDoc":oldDocModel,"nowDoc":docDataModel}); 249 + //loger.log('切换文档,当前文档和上一个显示的文档都需要更新状态');
  250 + loger.log({"oldDoc":oldDocModel,"nowDoc":docDataModel});
251 //更新当前选择的文档 251 //更新当前选择的文档
252 this.updaterDoc(docDataModel,docDataModel.itemIdx); 252 this.updaterDoc(docDataModel,docDataModel.itemIdx);
253 253
@@ -261,7 +261,7 @@ class DocApe extends Ape { @@ -261,7 +261,7 @@ class DocApe extends Ape {
261 //文档翻页 261 //文档翻页
262 documentSwitchPage(paramInfo){ 262 documentSwitchPage(paramInfo){
263 loger.log('文档翻页,documentSwitchPage'); 263 loger.log('文档翻页,documentSwitchPage');
264 - console.log(paramInfo); 264 + loger.log(paramInfo);
265 //console.log(this.docList); 265 //console.log(this.docList);
266 //获取已经存在的数据 266 //获取已经存在的数据
267 let docDataModel= this.docList[paramInfo.itemIdx]; 267 let docDataModel= this.docList[paramInfo.itemIdx];
@@ -349,7 +349,7 @@ class DocApe extends Ape { @@ -349,7 +349,7 @@ class DocApe extends Ape {
349 } 349 }
350 350
351 loger.log('tableInsertHandler 发送给客户端'); 351 loger.log('tableInsertHandler 发送给客户端');
352 - console.log(itemDataInfo); 352 + loger.log(itemDataInfo);
353 this._emit(MessageTypes.DOC_UPDATE,itemDataInfo);//用添加和更新都统一DOC_UPDATE 353 this._emit(MessageTypes.DOC_UPDATE,itemDataInfo);//用添加和更新都统一DOC_UPDATE
354 } 354 }
355 355
@@ -401,7 +401,7 @@ class DocApe extends Ape { @@ -401,7 +401,7 @@ class DocApe extends Ape {
401 loger.log('tableUpdateHandler 设置当前激活的文档id'); 401 loger.log('tableUpdateHandler 设置当前激活的文档id');
402 } 402 }
403 loger.log('tableUpdateHandler 发送给客户端'); 403 loger.log('tableUpdateHandler 发送给客户端');
404 - console.log(itemDataInfo); 404 + loger.log(itemDataInfo);
405 this._emit(MessageTypes.DOC_UPDATE,itemDataInfo); 405 this._emit(MessageTypes.DOC_UPDATE,itemDataInfo);
406 406
407 }else { 407 }else {
@@ -440,7 +440,9 @@ class DocApe extends Ape { @@ -440,7 +440,9 @@ class DocApe extends Ape {
440 this._emit(DocApe.DOC_JOIN_CHANNEL_SUCCESS); 440 this._emit(DocApe.DOC_JOIN_CHANNEL_SUCCESS);
441 },(GlobalConfig.mcuDelay+GlobalConfig.docDelay)|| 12000+GlobalConfig.docDelay); 441 },(GlobalConfig.mcuDelay+GlobalConfig.docDelay)|| 12000+GlobalConfig.docDelay);
442 }else { 442 }else {
  443 + setTimeout(() => {
443 this._emit(DocApe.DOC_JOIN_CHANNEL_SUCCESS); 444 this._emit(DocApe.DOC_JOIN_CHANNEL_SUCCESS);
  445 + },GlobalConfig.docDelay);
444 } 446 }
445 } 447 }
446 448
@@ -502,7 +504,7 @@ class DocApe extends Ape { @@ -502,7 +504,7 @@ class DocApe extends Ape {
502 docModelPdu.pageNum = _param.pageNum||1; 504 docModelPdu.pageNum = _param.pageNum||1;
503 docModelPdu.fileType=_param.fileType||""; 505 docModelPdu.fileType=_param.fileType||"";
504 docModelPdu.creatUserId=_param.creatUserId||"0"; 506 docModelPdu.creatUserId=_param.creatUserId||"0";
505 - docModelPdu.url =_param.url||"";//"http://101.200.150.192/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg"; 507 + docModelPdu.url ="";//这个地址没用到,数据太长占用资源 暂停使用//"http://101.200.150.192/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg";
506 docModelPdu.relativeUrl=_param.relativeUrl||"";//"/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg"; 508 docModelPdu.relativeUrl=_param.relativeUrl||"";//"/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg";
507 docModelPdu.curV=_param.curV||0; 509 docModelPdu.curV=_param.curV||0;
508 docModelPdu.curH=_param.curH||0; 510 docModelPdu.curH=_param.curH||0;
@@ -513,7 +515,7 @@ class DocApe extends Ape { @@ -513,7 +515,7 @@ class DocApe extends Ape {
513 docModelPdu.md5=_param.md5||"";//MD5 515 docModelPdu.md5=_param.md5||"";//MD5
514 docModelPdu.fileName=_param.fileName||"doc_"+_itemIdx;//文档的名字 516 docModelPdu.fileName=_param.fileName||"doc_"+_itemIdx;//文档的名字
515 docModelPdu.dynamicTS=_param.dynamicTS||"0";//文档上传后返回值中的字段dynamicTransferStatic 517 docModelPdu.dynamicTS=_param.dynamicTS||"0";//文档上传后返回值中的字段dynamicTransferStatic
516 - console.log(docModelPdu); 518 + loger.log(docModelPdu);
517 return docModelPdu; 519 return docModelPdu;
518 } 520 }
519 521