/*
kurento nodejs 开发常用库
web server
websocket server
mqtt
ms sql server
mysql server
kms
*/
var mysql = require('mysql');
const mssql = require('mssql')
var path = require('path');
var express = require('express');
var uuid = require('node-uuid');
var bodyParser = require('body-parser');
var ws = require('ws');
var minimist = require('minimist');
var url = require('url');
var kurento = require('kurento-client');
var fs = require('fs');
var https = require('https');
var http = require('http');
var Mqtt = require('mqtt');
var format = require('string-format');
format.extend(String.prototype);
var AliyunCore = require('@alicloud/pop-core');
var request = require('request');
var urlencode = require('urlencode');
class comm{
constructor(){
};
static cb(callback, p0 , p1 , p2) {
try{
if( callback){
callback(p0,p1,p2);
}
}
catch (e) {
console.log()
}
};
static extend ( a , b) {
try{
if( a==null || !a){
a = {};
}
if( b && b!=null){
for( p in b ){
a[p] = b[p];
}
}
}
catch (e) {
console.log(e);
}
return a;
};
static loopCall( items , actionFunction , onComplete){
try{
if( items && items!= null && items.length && items.length>0){
var acItems = [];
var acResults=[]
items.forEach(function (item) {
acItems.push(item);
});
var loadItem = function () {
if( acItems.length>0) {
var item = acItems.shift();
actionFunction(item, function (itemResult) {
acResults.push({i: item, r: itemResult});
loadItem();
})
}
else{
comm.cb(onComplete);
}
}
loadItem();
}
else{
comm.cb(onComplete);
}
}
catch (e) {
console.log(e);
}
}
}
/*
* web server
* */
function TWebSvrConfig() {
this.port="20022";
this.domain="88.88.cn";
this.keyFn="E:/app/kmsdev/dev/svr/appModules/common/4195813_**.**.cn.key";
this.certFn="E:/app/kmsdev/dev/svr/appModules/common/4195813_wss.**.cn.pem";
this.staticPaths={
"/":"E:/app/kmsdev/dev/static"
};
this.apiRootPath ="hhu"
}
function TWebSvr() {
this.config = new TWebSvrConfig();
this.routes = {
defaultApi: function (resApi , request , response ) {
resApi.error={errCode:0 , errMsg:"."} ;
resApi.data = "default."+ ( new Date()).getTime().toString();
response.send(JSON.stringify(resApi));
},
acHello: function (resApi , request , response ) {
resApi.error={errCode:0 , errMsg:"hello error."} ;
resApi.data = "hello."+ ( new Date()).getTime().toString();
response.send(JSON.stringify(resApi));
}
};
this.objs ={
app: null,
server:null
};
this.getApp = function () {
var me = this;
var app = express();
try{
//设置静态虚拟目录
for (sp in me.config.staticPaths) {
app.use(sp, express.static(me.config.staticPaths[sp]));
}
//设置编码
var urlencodedParser = bodyParser.urlencoded({extended: false});
app.use(urlencodedParser);
app.use(bodyParser.json());
var jsonParser = bodyParser.json();
//设置动态路由
var apiPath = ("/" + [me.config.apiRootPath, ":ac"].join("/")).replace("//", "/");
app.all(apiPath, jsonParser, function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "content-type");
res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
//API命令
var ac = req.params.ac;
//GET参数
var ps = comm.extend({}, req.query);
//返回结果
var result = {
ac: ac,
ps: ps,
error: null,
data: null
};
//响应入口
var handler = function (respResult) {
if (me.routes[respResult.ac]) {
me.routes[respResult.ac](respResult, req, res);
}
};
//POST参数调用
if (req.method == "POST") {
if( req.headers["content-type"].indexOf('application/json')>=0 ){
ps = comm.extend(ps, req.body);
handler(result);
}
else {
req.setEncoding('utf8');
req.on('data', function (data) {
try {
var obj = JSON.parse(data);
ps = comm.extend(ps, obj);
} catch (ee) {
console.log(ee)
}
});
req.on('end', function () {
handler(result);
});
}
} else if (req.method == "GET") {
//GET 方法调用
handler(result);
}
});
}
catch (e) {
console.log(e);
}
return app;
};
this.start = function (callback) {
var me = this;
try{
var options = {};
if (me.config.keyFn && me.config.keyFn != null && me.config.keyFn.length > 0) {
options = {
key: fs.readFileSync(me.config.keyFn),
cert: fs.readFileSync(me.config.certFn)
};
}
var app = me.getApp();
var httpsServer = https.createServer(options, app);
httpsServer.listen(me.config.port, function (err) {
me.objs.app = app;
var apiPath = ("/"+me.config.apiRootPath+"/<ac>").replace("//","/").replace("//","/");
var path = "https://{domain}:{port}{apiPath}".format({
domain: me.config.domain ,
port: me.config.port ,
apiPath: apiPath
});
console.log('start web server. api:', path);
me.objs.server = httpsServer;
comm.cb(callback , me.objs.server);
});
}
catch (e) {
console.log(e);
}
}
}
/*
* mqtt
* */
function TMqClient( ) {
this.config ={
server: 'ssl://gmggf8g.mqtt.iot.bj.baidubce.com:1884',
options: {
username: 'gmggf8g/peer',
password: 'a52bwKg22dCAuQzB',
clientId: 'busi_s_' + (new Date()).getTime().toString()
},
autoTopics:[]
};
this.client = null;
this.events={
onConnect: function () {},
onMsg: function (topic, msg) {}
};
this.getClientId = function () {
var res = "cid_";
res += ( new Date()).getTime().toString();
res += "_"+ parseInt( Math.random()*10000).toString();
return res;
}
this.disconnect = function () {
var me = this;
try{
if( me.client && me.client!=null && me.client.isConnected()){
me.client.disconnect();
me.client = null;
}
}
catch (e) {
console.log(e)
}
};
this.sendMsg = function (topic, msgInfo) {
var me = this;
try{
me.client.publish(topic , JSON.stringify(msgInfo));
}
catch (e) {
console.log(e)
}
};
this.initConfig = function (svr , uid , pwd , autoTopics) {
var me = this;
me.config.server = svr ;
me.config.options.username = uid;
me.config.options.password = pwd;
me.config.autoTopics = autoTopics;
};
this.reConnect = function (svr , uid , pwd , autoTopics) {
var me = this;
me.initConfig(svr, uid , pwd , autoTopics);
me.connect()
};
this.connect = function () {
var me = this;
try{
me.disconnect();
me.config.options.clientId = me.getClientId();
var client = Mqtt.connect(me.config.server, me.config.options);
client.on('error', function(error) {
console.error(error);
client= null;
});
client.on('connect', function() {
try {
console.log('Connected. Client id is: ' + me.config.options.clientId);
if( me.config.autoTopics){
try {
me.config.autoTopics.forEach(function (topic) {
client.subscribe(topic);
})
}
catch (er) {
console.log(er);
}
}
comm.cb(me.events.onConnect);
}
catch (er) {
console.log(er)
}
});
client.on('disconnect', function() {
try {
console.log('disconnect. Client id is: ' + me.config.options.clientId);
}
catch (er) {
console.log(er)
}
});
client.on('message', function(topic, data) {
try {
var msgInfo = JSON.parse(data);
me.events.onMsg(topic , msgInfo);
}
catch (er) {
console.log(er)
}
});
me.client = client;
}
catch (e) {
console.log(e)
}
};
}
/*
* websocket
* */
function TWebSocketConfig() {
this.path ="/wss"
}
function TWebSocket() {
this.config = new TWebSocketConfig();
this.webServer = null;
this.websocketServer = null;
this.sessions = {};
this.events = {
onsessionConnected : function (session) {
},
onsessionDisConnected : function (sessionId) {
},
onRecMsg : function (session , msg) {
}
};
this.start = function (server) {
var me = this;
try{
me.webServer = server;
var wsSvr = new ws.Server({
server:server ,
path: me.config.path
});
wsSvr.Server.on('connection', function (ws) {
me.websocketServer = wsSvr;
var sessionId = "sid_"+(new Date()).getTime().toString()+"_"+
parseInt(math.random()*1000).toString();
ws.sessionId = sessionId;
me.sessions[sessionId] = ws;
comm.cb(me.events.onsessionConnected(ws));
ws.on('error', function(error) {
console.log(error);
me.closeSession(ws.sessionId);
});
ws.on('close', function () {
try{
if(me.sessions[ws.sessionId]){
delete me.sessions[ws.sessionId];
}
ws.close();
comm.cb(me.events.onsessionDisConnected(ws.sessionId));
}
catch (eer) {
console.log(eer)
}
});
ws.on('message', function (_message) {
try{
var message = JSON.parse(_message);
comm.cb(me.events.onRecMsg, message);
}
catch (er) {
console.log(er);
}
});
})
}
catch (e) {
console.log(e);
}
};
}
/*
* ms sql server
* */
function TMsDB () {
this.config = {
msDB: {
server : 'video.xmgkfw.cn',
user : 'sa',
password : 'ABCabc123',
//database : 'rtcChannel',
database : 'rtcChannel',
port : 8201,
options: {
encrypt: true //使用windows azure,需要设置次配置。
},
pool: {
min: 0,
idleTimeoutMillis: 3000
}
},
sqlPath:"e:/app/kmsdev/dev/svr/sqls"
};
this.pool=null;
this.query = function (sql , ps , callback) {
var me = db;
var queryRes ={
result:null
};
try{
if( me.pool==null){
me.pool = new mssql.ConnectionPool(me.config.msDB);
}
me.pool.connect(function (errConn , connection) {
if( errConn ){
queryRes.error = errConn;
callback (queryRes);
}
else{
var dbReq = connection.request();
if( ps && ps!=null){
var getType = function (arg) {
var dataType= mssql.NVarChar;
if( arg && typeof(arg) == "string"){
dataType= mssql.NVarChar;
}
else if( arg && typeof(arg) == "number" && !isNaN(arg)){
if( Number.isInteger(arg)){
dataType= mssql.Int;
}
else{
dataType = mssql.Float;
}
}
return dataType;
}
for ( var p in ps){
var v = ps[p];
var vType = getType(v);
dbReq.input(p,vType,v);
}
}
dbReq.query(sql , function (erQuery, resQuery) {
try{
queryRes.result = resQuery;
callback (queryRes);
}
catch (eer) {
console.log(eer);
}
})
connection.release();
}
})
}
catch (e) {
console.log(e)
}
};
this.queryByFn= function (sqlFn , ps , callback) {
var me = db;
var queryRes ={
result:null
};
try{
var fn = [me.config.sqlPath , sqlFn].join('/');
fn = fn.replace("\\",'/').replace('//','/');
fn = fn + (fn.indexOf('.txt')>0?"":".txt");
if( fs.existsSync(fn)){
var sql = fs.readFileSync(fn, 'utf-8');
me.query(sql , ps , callback);
}
else{
queryRes.error="query Key is error.["+sqlFn+"]";
callback(queryRes);
}
}
catch (e) {
console.log(e)
}
}
}
/*
* my sql server
* */
function TMyDB() {
this.apps={
kms:{
host:"tjiot.**.cn" ,
port:53306,
uid:"root",
pwd:"hhuc1115",
db:"kmsv10" ,
sqlPath:"E:/app/kmsdev/dev/svr/sqls"
},
hhRemoteAssist:{
host:"tjiot.**.cn" ,
port:53306,
uid:"root",
pwd:"hhuc1115",
db:"hhRemoteAssist" ,
sqlPath:"E:/app/kmsdev/dev/svr/sqls"
}
};
this.pools={};
this.getConn = function (appName , callback) {
var me = this;
var res ={ conn:null};
try{
if( me.apps[appName] ){
var dbInfo = me.apps[appName];
if( !dbInfo.pool){
dbInfo.pool = mysql.createPool({
host: dbInfo.host ,
port: dbInfo.port ,
user: dbInfo.uid ,
password: dbInfo.pwd ,
database: dbInfo.db,
connectionLimit:100
});
}
dbInfo.pool.getConnection(function (err, conn) {
res.error = err;
res.conn = conn;
callBack(callback , res);
})
}
else{
res.error="appName is error."
callBack(callback , res);
}
}
catch (e) {
console.log(e);
}
};
this.query = function (appName , sql , ps , callback) {
var res ={ result:null};
var me = this;
try{
me.getConn(appName , function (resConn) {
if( resConn.error){
callBack(callback, resConn);
}
else {
resConn.conn.query(sql, ps, function (errQuery, results, fields) {
resConn.conn.release();
if (errQuery) {
res.error = errQuery;
callBack(callback, res);
console.log(errQuery, sql, ps);
} else {
res.result = JSON.parse(JSON.stringify(results));
callBack(callback, res);
}
})
}
})
}
catch (e) {
console.log(e);
}
};
this.queryByPath = function (appName , sqlPath , ps , callback) {
var res ={ result:null};
var me = this;
try{
if( me.apps[appName] ){
var absPath = me.apps[appName].sqlPath+"/"+sqlPath;
absPath = absPath.replace("//","/");
if( absPath.indexOf(".txt")<=0 ){
absPath = absPath+".txt";
}
fs.exists(absPath, function (flag) {
if( flag){
var sql = fs.readFileSync(fn, 'utf-8');
me.query(appName, sql , ps , function (resDB) {
res = resDB;
callBack(callback , res);
})
}
else{
res.error = "sqlPath is error.";
callBack(callback , res);
}
})
}
else{
res.error="appName is error."
callBack(callback , res);
}
}
catch (e) {
console.log(e);
}
};
}
/*
* kurento
* */
function TKurentoInf(){
this.config={
kmsUrl:"wss://ssl.**.cn:40014/kurento"
};
this.tags={};
this.objs={
client: null,
serverMsnager: null,
kmsObjs:{}
};
this.getClient = function (callback) {
var me = this;
try{
if( me.objs.client && me.objs.client!= null){
comm.cb(callback , me.objs.client);
}
else{
kurento(me.config.kmsUrl, function (erC , client) {
client.getServerManager(function (erS , svr) {
client.serverMsnager = svr;
me.objs.client = client;
me.objs.serverMsnager = svr;
me.getChilds(svr, function (kmsObjs) {
me.objs.kmsObjs = kmsObjs;
comm.cb(callback, client);
})
})
})
}
}
catch (e) {
console.log(e)
}
};
this.getChilds = function ( rootObj , callback) {
var me = this;
try{
var resultItems={};
var getItems = function (kmsObj, onGetItems) {
var acFun = kmsObj.id.indexOf("ServerManager")>0?"getPipelines": "getChildren";
kmsObj[acFun](function (erItems, items) {
var index =0;
var loadItem = function () {
if( index<items.length){
var item = items[index];
me.getObjInfo(item, function () {
resultItems[item.id] = item;
getItems(item, function () {
index++;
loadItem();
})
})
}
else{
//console.log(kmsObj.id, index, items.length, resultItems.length)
onGetItems();
}
}
loadItem();
})
}
getItems(rootObj, function () {
comm.cb(callback, resultItems);
});
}
catch (e) {
console.log(e)
}
};
this.setObjInfo = function ( obj , name , tags, callback) {
var me = this;
try{
obj.setName( name , function (erName ) {
var ps = Object.keys(tags);
var vs = Object.values(tags);
var index =0;
var acItem = function () {
if( index<ps.length){
obj.addTag((ps[index]).toString(), (vs[index]).toString(), function (erTag) {
index++;
acItem();
})
}
else{
obj.info={
id: obj.id,
name:name,
tags:tags
};
me.objs.kmsObjs[obj.id] = obj;
comm.cb(callback, obj)
}
}
acItem();
})
}
catch (e) {
console.log(e)
}
};
this.getObjInfo = function ( obj , callback) {
var me = this;
try{
var info ={
id:obj.id ,
name:"",
tags:{}
};
obj.getName(function (erName, name) {
info.name = name;
obj.getTags(function (erTags, tags) {
tags.forEach(function (tag) {
info.tags[tag.key] = tag.value;
})
obj.info= info;
comm.cb(callback, info, obj);
})
})
}
catch (e) {
console.log(e)
}
};
this.createObject= function(objType , parent , url , name , tags , callback ){
var me = this;
try{
var res= null;
var err = {
errorCode : -1 ,
err:"objType is error."
};
me.getClient(function(client){
var onCreate = function(obj){
me.setObjInfo(obj,name,tags,function () {
comm.cb(callback, obj);
})
}
if( objType=="MediaPipiline"){
client.create("MediaPipeline", function(erObj,obj){
onCreate(obj);
});
}
else if (
["DispatcherOneToMany","Composite","Dispatcher","WebRtcEndpoint"].indexOf(objType)>=0
){
pipe.create(objType, function (erObj , obj) {
onCreate(obj);
})
}
else if (objType=="PlayerEndpoint"){
pipe.create("PlayerEndPoint",{uri: url}, function (erObj , obj) {
obj.on("EndOfStream", function () {
obj.play();
})
obj.play(function (erPlayer) {
if( erPlayer){
console.log('play error.', url , erPlayer);
}
onCreate(obj);
});
})
}
else{
comm.cb(callback, res , err);
}
});
}
catch(er){
console.log(e);
}
};
this.dispatch= function( srcId , targetId , callback ){
var me = this;
try{
var res ={
state:0,
error:""
} ;
if( !me.objs.kmsObjs[srcId]){
res.state = -1;
res.error="srcId is error";
comm.cb(callback,res)
}
else if( !me.objs.kmsObjs[targetId]){
res.state = -2;
res.error="targetId is error";
comm.cb(callback,res)
}
else{
var ids = srcId.split("/");
var hubId = [ids[0],ids[1]].join("/");
if( !me.objs.kmsObjs[hubId]){
res.state = -3;
res.error = "hub is empty."
}
else{
var hub = me.objs.kmsObjs[hubId];
var src = me.objs.kmsObjs[srcId];
var target = me.objs.kmsObjs[targetId];
hub.connect(src, target, function (erConnect) {
res.state = erConnect?-4:1;
res.error = erConnect;
comm.cb(callback, res);
})
}
}
}
catch(er){
console.log(e);
}
}
}
var kms = new TKurentoInf();
kms.getClient(function (client) {
Object.values(kms.objs.kmsObjs).forEach(function (obj) {
console.log(obj.info)
})
})
module.exports={
comm:comm ,
TWebSvr: TWebSvr,
TWebSocket:TWebSocket,
TMsDB:TMsDB,
TMyDB:TMyDB,
TKurentoInf:TKurentoInf
};