client.js


/**
 * @module Client
 * @author roymond.wang
 * @since 2018-08-30
 * @desc Client模块, 信令系统的入口。
 * 
 * 
 * @example 
 * var Clinet = ModuleBase.use(ModulesEnum.client);
 */

if(!log){
   var log = log4javascript.getLogger();
}

if(!bugout){
	var bugout = null;
}

var signalClient = null;
var Task_Id = 0; //每次自增长

var rtmVersion = "1.0.0.0";

ModuleBase.define("Client", ["RestServer","RtmManager","RtmServer","ClientUser","InviteManager","RemoteControlManager","ChatManager","RpcManager","Error"], function(RestServer,RtmManager,RtmServer,ClientUser,InviteManager,RemoteControlManager,ChatManager,RpcManager,Error) {
   
	var Client = function(serverURI,accessToken) {
		/**
         * @desc Client级别回调的枚举
         * @readonly
         * @enum {string}
         */
		this.ClientCallbackEnum = {
			NATIVE_PAYLOAD_NOTIFY: 'native.payload',
		};
		
		this.serverURI = serverURI;
		this.accessToken = accessToken;
		
		this.mqttWSAddr = null;
		
		this.restServer =  new RestServer();
		this.rtmManager = null;
		this.rtmServer = null;
		this.inviteManager = null;
		this.remoteControlManager = null;
		this.chatManager = null;
		this.rpcManager = null;
		this.selfUser = null;
		
		this.eventEmitter = new EventEmitter();
		
		this.topicReservedWords = ['/u/','/g/','/s'];
		
		signalClient = this;
	};
	
	
	/**
	 * @desc 获取rtm client的版本号
	 * @returns {String} - 版本号
	 * 
	 * @example 
	 * var Version = avdEngine.getVersion();
	 */
	Client.prototype.getVersion = function() {
		return "rtm-" + rtmVersion;
	};
	
	
	/**
	 * @desc 设置日志显示方式和日志级别
	 * @param {Appender} appenderModel - 日志显示方式(枚举型), 默认值为Appender.browserConsole
	 * @param {LogLevel} logLevel - 日志级别(枚举型),默认值为LogLevel.error
	 * 
	 * @example 
	 * avdEngine.setLog(Appender.browserConsole, LogLevel.debug);
	 */
	Client.prototype.setLog = function(appenderModel, logLevel) {
		var appender;
		if(appenderModel == Appender.alert) {
			appender = new log4javascript.AlertAppender();
		} else if(appenderModel == Appender.inpage) {
			appender = new log4javascript.InPageAppender();
		} else if(appenderModel == Appender.popup) {
			appender = new log4javascript.PopUpAppender();
		} else if(appenderModel == Appender.browserConsole) {
			appender = new log4javascript.BrowserConsoleAppender();
		}

		if(logLevel == LogLevel.all) {
			appender.setThreshold(log4javascript.Level.ALL);
		} else if(logLevel == LogLevel.trace) {
			appender.setThreshold(log4javascript.Level.TRACE);
		} else if(logLevel == LogLevel.debug) {
			appender.setThreshold(log4javascript.Level.DEBUG);
		} else if(logLevel == LogLevel.info) {
			appender.setThreshold(log4javascript.Level.INFO);
		} else if(logLevel == LogLevel.warn) {
			appender.setThreshold(log4javascript.Level.WARN);
		} else if(logLevel == LogLevel.error) {
			appender.setThreshold(log4javascript.Level.ERROR);
		} else if(logLevel == LogLevel.fatal) {
			appender.setThreshold(log4javascript.Level.FATAL);
		} else if(logLevel == LogLevel.off) {
			appender.setThreshold(log4javascript.Level.OFF);
		}
		appenderLayout(appender);
	};
	
	function appenderLayout(appender) {
		var popUpLayout = new log4javascript.PatternLayout("%d{yyyy-MM-dd HH:mm:ss SSS} %-5p - %m{1}%n");
		appender.setLayout(popUpLayout);
		log.addAppender(appender);
	};
	
   
	/**
	 * @desc 用户登陆
	 * @async
	 * @param {String} account  -登陆帐号
	 * @param {String} password -登陆密码 - 可以不填
	 */
   Client.prototype.login = function(account,password) {
       	  var deferred = when.defer();
		  var self = this;
		  self.restServer.getMqttWSAddr(self.serverURI,self.accessToken).then(function(mqttWSAddr){
				log.info("===client.login(),restServer.getMqttWSAddr(), mqttWSAddr:",mqttWSAddr);
				self.mqttWSAddr = mqttWSAddr;
				self.rtmManager = new RtmManager(self.mqttWSAddr,account,password);
				self.rtmManager.connect().then(function(rtmClient){
					   signalClient.rtmServer = new RtmServer(rtmClient);
					   signalClient.rtmServer.subscribe("/u/" + account);
					   
					   var clientUser = new ClientUser(account,password);
					   self.selfUser = clientUser;
					   
					   deferred.resolve();
				}).otherwise(function(error){
					   deferred.reject(error);
				});
	 	   }).otherwise(function(error){
	 	   	    log.error("===client.login(),error:",error);
	 	   	    deferred.reject(error);
	 	   });
		 
        return deferred.promise;
	};
	
	

	
	/**
	 * @desc 用户登出
	 * @async
	 * @param {int} reson -登出原因
	 */
	Client.prototype.logout = function(reson) {
		  var deferred = when.defer();
		  var self = this;
		  try{
		  	  this.rtmServer.end();
		      signalClient = null;
		      self.selfUser = null;
		  	  deferred.resolve();
		  }catch(error){
		  	  deferred.reject(error);
		  }
          return deferred.promise;
	};
	
	
	/**
	 * @desc 获取邀请管理类
	 * @returns {InviteManager} - inviteManager 邀请管理类
	 */
	Client.prototype.getInviteManager = function(){
		if(! this.inviteManager){
		    this.inviteManager = new InviteManager();
		}
	    return this.inviteManager;
	};
	
	
	
	/**
	 * @desc 获取远程管理类
	 * @returns {RemoteControlManager} - remoteControlManager 远程管理类
	 */
	Client.prototype.getRemoteControlManager = function(){
		if(! this.remoteControlManager){
		    this.remoteControlManager = new RemoteControlManager();
		}
	    return this.remoteControlManager;
	};
	
	
	
	/**
	 * @desc 获取聊天管理类
	 * @returns {ChatManager} - chatManager 聊天管理类
	 */
	Client.prototype.getChatManager = function(){
		if(! this.chatManager){
		    this.chatManager = new ChatManager();
		}
	    return this.chatManager;
	};
	
	
	/**
	 * @desc 获取RPC管理类
	 * @returns {RpcManager} - rpcManager RPC管理类
	 */
	Client.prototype.getRpcManager = function(){
		if(! this.rpcManager){
		    this.rpcManager = new RpcManager();
		}
	    return this.rpcManager;
	};
	
	
	Client.prototype.getServeTime = function(){
		var dt = new Date;
		dt.setMinutes(dt.getMinutes() + dt.getTimezoneOffset()); // 当前时间(分钟) + 时区偏移(分钟)
		var timestamp = dt.getTime(); //格林尼治时间戳(毫秒数)
		timestamp = Math.round(timestamp / 1000); //精确到秒 
		return timestamp;
	};
	
	/**
	 * @desc 没有封闭,原生的MQTT消息发布
	 * @async
	 * @param {Object} topic -主题
	 * @param {Object} payload -内容
	 */
    Client.prototype.nativePublish = function(topic,payload){
    	 var deferred = when.defer();
		 var isExit = arrayUtil.contains(this.topicReservedWords, topic);
		 if(isExit){
		 	   var nativePublishError = new Error(ErrorConstant.mqtt_topic_reservedword_error);
		 	   deferred.reject(nativePublishError);
		 }else{
		 	  this.rtmServer.publish(topic,payload); 
		 	   deferred.resolve();
		 }
         return deferred.promise;
    };
     
     /**
      * @desc 没有封闭,原生的MQTT消息订阅
	  * @async
      * @param {Object} topic-主题
      */
     Client.prototype.nativeSubscribe = function(topic){
     	 var deferred = when.defer();
		 var isExit = arrayUtil.contains(this.topicReservedWords, topic);
		 if(isExit){
		 	   var nativePublishError = new Error(ErrorConstant.mqtt_topic_reservedword_error);
		 	   deferred.reject(nativePublishError);
		 }else{
     	      this.rtmServer.subscribe(topic); 
     	       deferred.resolve();
		 }
         return deferred.promise;
     };
     
     
     /**
      * @desc 获取主题的保留字。如果原生的MQTT消息发布,主题中含有保留字会抛错
      */
     Client.prototype.getTopicReservedWords = function(){
     	 return this.topicReservedWords;
     };
     
	
	
	/**
     * @desc Client级别的回调
     * @param {ClientCallback} type - 回调枚举标识
     * @param {Object} callback -回调方法名,可以自定义
     *     
     */
	Client.prototype.addCallback = function(type, callback) {
	    this.eventEmitter.on(type, callback);
	};
	
	
	Client.prototype.offCallback = function(types) {
	   for(var key in types) {
           var type = types[key]; 
	   	   this.eventEmitter.off(type);
	   }
	};
	
	return Client;
});