gfeedclient.js

var WebSocket = require("ws");
var constants = require("./constants");
var url="";
var api_key="";
var Authenticated = false;
var UserDisconnection = false;
var auto_reconnect=true;
var previous_call=-1;
var MULTIPLIER=30;
var TIMEOUT=1000;
var FORCED_EXIT_TIMEOUT=100;
var LOCK_GET_EXCHANGES=false;
var LOCK_GET_INSTRUMENTS_ON_SEARCH=false;
var LOCK_GET_INSTRUMENTS=false;
var LOCK_GET_LAST_QUOTE=false;
var LOCK_GET_LAST_QUOTE_ARRAY=false;
var LOCK_GET_SNAPSHOT=false;
var LOCK_GET_HISTORY_TICK=false;
var LOCK_GET_HISTORY_OHLC=false;
var LOCK_GET_INSTRUMENTS_TYPES=false;
var LOCK_GET_PRODUCTS=false;
var LOCK_GET_EXPIRY=false;
var LOCK_GET_OPTION_TYPES=false;
var LOCK_GET_STRIKE_PRICES=false;
var LOCK_GET_LIMITATION=false;
var LOCK_GET_SERVER_INFO=false;
var LOCK_GET_MARKET_MESSAGE=false;
var LOCK_GET_EXCHANGE_MESSAGE=false;
var LOCK_SUBSCRIBE_REALTIME=false;
var LOCK_SUBSCRIBE_REALTIME_SNAPSHOT=false;
/**
 * @constructor
 * @name DhelmGfeed
 * @param {Object} params
 * @param {string} params.ws_url The web socket url(required).
 * @param {string} params.api_key The api key you have got on subscription(required).
 * @param {boolean} params.auto_reconnect If false not autoreconnection attempt will be made(optional).
 * @param {int} params.multiplier Multliper to increase the duration of delay for responses with longer length(optional).
 * @param {int} params.synchronization_delay  The delay required to receive response for a request(optional).
 * @param {int} params.function_release_time The systematic delay between subsequent calls to a function(optional). 
 */
var DhelmGfeed = function(params) {
    if (params.ws_url==null) {
        throw "URL cannot be null";
    } 
    if(params.api_key==null){
        throw "API-KEY cannot be null";
    }
    url=params.ws_url;
    api_key=params.api_key;
    if(params.auto_reconnect!=null)auto_reconnect=params.auto_reconnect;
    if(params.multiplier!=null)MULTIPLIER=params.multiplier;
    if(params.synchronization_delay!=null)TIMEOUT=params.synchronization_delay;
    if(params.function_release_time!=null)FORCED_EXIT_TIMEOUT=params.function_release_time;
    var ws = null;
    var subscribrd_exchanges=constants.RESULT_NOT_PREPARED;
    var instrument_list_on_search=constants.RESULT_NOT_PREPARED;
    var instrument_list=constants.RESULT_NOT_PREPARED;
    var last_quote=constants.RESULT_NOT_PREPARED;
    var last_quote_array=constants.RESULT_NOT_PREPARED;
    var snapshot=constants.RESULT_NOT_PREPARED;
    var hisotical_tick=constants.RESULT_NOT_PREPARED;
    var hisotical_ohlc=constants.RESULT_NOT_PREPARED;
    var instrument_types=constants.RESULT_NOT_PREPARED;
    var products=constants.RESULT_NOT_PREPARED;
    var expiry_dates=constants.RESULT_NOT_PREPARED;
    var option_types=constants.RESULT_NOT_PREPARED;
    var strike_prices=constants.RESULT_NOT_PREPARED;
    var limitation=constants.RESULT_NOT_PREPARED;
    var server_info=constants.RESULT_NOT_PREPARED;
    var market_message=constants.RESULT_NOT_PREPARED;
    var exchange_message=constants.RESULT_NOT_PREPARED;
    var real_time_result=constants.RESULT_NOT_PREPARED;
    var real_time_snapshot_result=constants.RESULT_NOT_PREPARED;
    var SYNCHRONIZATION_EXP=Date.now()+TIMEOUT;
    var count=0;
    console.log(url);
    console.log(api_key);
    /**
	 * Initiate a websocket connection
	 * @memberOf DhelmGfeed
	 * @method connect
	 * @instance
	 */
    this.connect = function(callback) {
        if(ws && (ws.readyState == ws.CONNECTING || ws.readyState == ws.OPEN)) return;
        ws = new WebSocket(url);
        ws.onopen = function() {
            Authenticate();
        };
        ws.onmessage=function(e){
            if(e!=null){
                if(e.data.includes('"Complete":true') 
                || e.data.includes('"AllowVMRunning":false') 
                    ||e.data.includes('"AllowServerOSRunning":false')){
                        console.log(e.data);
                        Authenticated=true;
                        if(Authenticated){
                            console.log("Authenticated");
                            if(callback)
                               callback(true);
                        }
                }
            }            
        };
        ws.onerror = function (error) {
            if(this && this.readyState == this.OPEN) {
                Authenticated=false;
                this.disconnect();
            }
         };
        ws.onclose = function(e) {
            if(UserDisconnection==false){
               Authenticated=false;
               if(!UserDisconnection)
               onDisconnect(e);
            }
        };
    };
    /**
     * Disconnects the web socket connection
	 * @memberOf DhelmGfeed
	 * @method disconnect
     * @param {boolean} force_disconnect User promted disconnect
	 * @instance
	 */
	this.disconnect = function(force_disconnect) {
		if(ws && ws.readyState != ws.CLOSING && ws.readyState != ws.CLOSED) {
            Authenticated=false;
            ws.close();
            if(force_disconnect)
            UserDisconnection = true;
		}
    }
    /**
	 * Check if the web socket is connected
	 * @memberOf DhelmGfeed
	 * @method connected
	 * @instance
	 * @returns {bool}
	 */
	this.connected = function() {
		if(ws && ws.readyState == ws.OPEN) {
			return true;
		} else {
			return false;
		}
    };
    
    /**
	 * Get the list of subscribed exchanges
	 * @memberOf DhelmGfeed
	 * @method getExchanges
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getExchanges=function(callback){
        if(!Authenticated)return;
        if(!LOCK_GET_EXCHANGES){
            console.log("Trying to fetch subscribed exchanges..");
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_EXCHANGES=true;
            r(1,forceed_exit_time);
            if(Authenticated) {
                subscribed_exchanges=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetSubscribedExchanges();
                ws.onmessage=function(e){
                if(e!=null){
                     if(e.data.includes('"MessageType":"'+constants.MESSAGE_EXCHANGE_RESULT+'"') ){
                            console.log(e.data);
                            subscribrd_exchanges=e.data;
                            count--;
                            LOCK_GET_EXCHANGES=false;
                            if(callback){
                               callback(subscribrd_exchanges);
                            }
                      }
                     }
                };
              },(count>0)?getSynchronizationDelay(1):1);
        }
        }
    };
    /**
	 * Returns array of max. 20 instruments (properties) by selected exchange and ‘search word’
	 * @memberOf DhelmGfeed
	 * @method getInstrumentsOnSearch
     * @param {object} param 
     * @param {string} param.exchange The exchange(required).
     * @param {string} param.search_word The search word(required).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getInstrumentsOnSearch=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_INSTRUMENTS_ON_SEARCH){
            console.log("Trying to fetch instruments on search..");
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_INSTRUMENTS_ON_SEARCH=true;
            r(2,forceed_exit_time);
            if(Authenticated) {
                instrument_list_on_search=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetInstrumentsOnSearch(param);
                ws.onmessage=function(e){
                if(e!=null){
                     if(e.data.includes('"MessageType":"'+constants.MESSAGE_INSTRUMENTS_ON_SEARCH_RESULT+'"') ){
                            console.log(e.data);
                            instrument_list_on_search=e.data;
                            count--;
                            LOCK_GET_INSTRUMENTS_ON_SEARCH=false;
                            if(callback)
                               callback(instrument_list_on_search);
                      }
                     }
                };
              },(count>0)?getSynchronizationDelay(2):1);
        }
        }
    };
    /**
	 * Returns array of instruments (properties) by selected exchange.
	 * @memberOf DhelmGfeed
	 * @method getInstruments
     * @param {object} param 
     * @param {string} param.exchange The exchange(required).
     * @param {string} param.instrument_type Name of Supported InstrumentType.E.g. FUTIDX(optional).
     * @param {string} param.product Name of Supported Product..E.g. BANKNIFTY(optional).
     * @param {string} param.expiry Value of Supported Expiry..E.g. 30AUG2018(optional).
     * @param {string} param.optiontype Name of the option type..E.g. CE(optional).
     * @param {string} param.strikeprice String representation of the strike price.(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getInstruments=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_INSTRUMENTS){
            console.log("Trying to fetch instruments..");
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_INSTRUMENTS=true;
            r(3,forceed_exit_time);
            if(Authenticated) {
                instrument_list=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetInstruments(param);
                ws.onmessage=function(e){
                if(e!=null){
                     if(e.data.includes('"MessageType":"'+constants.MESSAGE_INSTRUMENTS_RESULT+'"') ){
                            console.log(e.data);
                            instrument_list=e.data;
                            count--;
                            LOCK_GET_INSTRUMENTS=false;
                            if(callback)
                               callback(instrument_list);
                      }
                     }
                };
              },(count>0)?getSynchronizationDelay(3):1);
        }
        }
    };
    /**
	 * Returns detailed information about Last Trade Price (LTP)
	 * @memberOf DhelmGfeed
	 * @method getLastQuote
     * @param {object} param 
     * @param {string} param.exchange The exchange(required).
     * @param {string} param.instrument_identifier The instrument identifier(required).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getLastQuote=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_LAST_QUOTE){
            console.log("Trying to fetch last quote.");
            if (param.exchange==null) {
                throw "Invalid Parameter/exchange cannot be null.";
            }
            if (param.instrument_identifier==null) {
                throw "Invalid Parameter/instrument_identifier cannot be null.";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_LAST_QUOTE=true;
            r(4,forceed_exit_time);
            if(Authenticated) {
                last_quote=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetLastQuote(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_LAST_QUOTE_RESULT+'"') ){
                            console.log(e.data);
                            last_quote=e.data;
                            count--;
                            LOCK_GET_LAST_QUOTE=false;
                            if(callback)
                               callback(last_quote);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(4):1);
            }
        }
    };
    /**
	 * Returns detailed information about Last Trade Price (LTP) of Multiple Symbols (max 25 in single call)
	 * @memberOf DhelmGfeed
	 * @method getLastQuoteArray
     * @param {object} param 
     * @param {string} param.exchange The exchange(required).
     * @param {Array} param.instrument_identifiers The instrument identifiers(required).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getLastQuoteArray=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_LAST_QUOTE_ARRAY){
            console.log("Trying to fetch last quote array.");
            if (param.exchange==null) {
                throw "Invalid Parameter/exchange cannot be null.";
            }
            if (param.instrument_identifiers==null) {
                throw "Invalid Parameter/instrument_identifiers cannot be null.";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_LAST_QUOTE_ARRAY=true;
            r(5,forceed_exit_time);
            if(Authenticated) {
                last_quote_array=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetLastQuoteArray(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_LAST_QUOTE_ARRAY_RESULT+'"') ){
                            console.log(e.data);
                            last_quote_array=e.data;
                            count--;
                            LOCK_GET_LAST_QUOTE_ARRAY=false;
                            if(callback)
                               callback(last_quote_array);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(5):1);
            }
        }
    };
    /**
	 * Returns last snapshot of Multiple Symbols (max 25 instruments in single call)
	 * @memberOf DhelmGfeed
	 * @method getSnapshot
     * @param {object} param 
     * @param {string} param.exchange The exchange(required).
     * @param {Array} param.instrument_identifiers The instrument identifiers(required).
     * @param {string} param.periodicity The periodicity/"HOUR" or "MINUTE"(optional).
     * @param {number} param.period The period.E.g. 1,2,3 etc.(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getSnapshot=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_SNAPSHOT){
            console.log("Trying to fetch the snapshot data.");
            if (param.exchange==null) {
                throw "Invalid Parameter/exchange cannot be null.";
            }
            if (param.instrument_identifiers==null) {
                throw "Invalid Parameter/instrument_identifiers cannot be null.";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_SNAPSHOT=true;
            r(5,forceed_exit_time);
            if(Authenticated) {
                snapshot=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetSnapshot(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_SNAPSHOT_RESULT+'"') ){
                            console.log(e.data);
                            snapshot=e.data;
                            count--;
                            LOCK_GET_SNAPSHOT=false;
                            if(callback)
                               callback(snapshot);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(6):1);
            }
        }
    };
     /**
	 * Returns array with historical data (array of Ticks)
	 * @memberOf DhelmGfeed
	 * @method getHistoricalTick
     * @param {object} param 
     * @param {string} param.exchange The exchange(required).
     * @param {string} param.instrument_identifier The instrument identifier(required).
     * @param {number} param.from The from time in unix timestamp(required).
     * @param {number} param.to The to time in unix timestamp(required).
     * @param {number} param.max Numerical value of maximum records that should be returned. 
     * Default = 0 (means all available data).(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getHistoricalTick=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_HISTORY_TICK){
            console.log("Trying to fetch historical tick data.");
            if (param.exchange==null) {
                throw "Invalid Parameter/exchange cannot be null.";
            }
            if (param.instrument_identifier==null) {
                throw "Invalid Parameter/instrument_identifiers cannot be null.";
            }
            if (param.from==null) {
                throw "Invalid Parameter/from cannot be null.";
            }
            if (param.to==null) {
                throw "Invalid Parameter/to cannot be null.";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_HISTORY_TICK=true;
            r(7.1,forceed_exit_time);
            if(Authenticated) {
                hisotical_tick=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetHistoricalTick(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_HISTORY_TICK_RESULT+'"') ){
                            console.log(e.data);
                            hisotical_tick=e.data;
                            count--;
                            LOCK_GET_HISTORY_TICK=false;
                            if(callback)
                               callback(hisotical_tick);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(7.1):1);
            }
        }
    };
    /**
	 * Returns array with historical data (array of OHLC)
	 * @memberOf DhelmGfeed
	 * @method getHistoricalOHLC
     * @param {object} param 
     * @param {string} param.exchange The exchange(required).
     * @param {string} param.instrument_identifier The instrument identifier(required).
     * @param {number} param.periodicity "HOUR"."MINUTE"."DAY","WEEK", or "MONTH"(required).
     * @param {number} param.from The from time in unix timestamp(required).
     * @param {number} param.to The to time in unix timestamp(required).
     * @param {number} param.max Numerical value of maximum records that should be returned. 
     * Default = 0 (means all available data).(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getHistoricalOHLC=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_HISTORY_OHLC){
            console.log("Trying to fetch historical ohlc data.");
            if (param.exchange==null) {
                throw "Invalid Parameter/exchange cannot be null.";
            }
            if (param.instrument_identifier==null) {
                throw "Invalid Parameter/instrument_identifiers cannot be null.";
            }
            if (param.periodicity==null) {
                throw "Invalid Parameter/periodicity cannot be null.";
            }
            if (param.from==null) {
                throw "Invalid Parameter/from cannot be null.";
            }
            if (param.to==null) {
                throw "Invalid Parameter/to cannot be null.";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_HISTORY_OHLC=true;
            r(7.2,forceed_exit_time);
            if(Authenticated) {
                hisotical_ohlc=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetHistoricalOHLC(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_HISTORY_OHLC_RESULT+'"') ){
                            console.log(e.data);
                            hisotical_ohlc=e.data;
                            count--;
                            LOCK_GET_HISTORY_OHLC=false;
                            if(callback)
                               callback(hisotical_ohlc);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(7.2):1);
            }
        }
    };
    /**
	 *Get the list of instrument types for the given exchange
	 * @memberOf DhelmGfeed
	 * @method getInstrumentTypes
     * @param {object} param 
     * @param {string} param.exchange The exchange.
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getInstrumentTypes=function(param,callback){
        if(!Authenticated)return;
      if(!LOCK_GET_INSTRUMENTS_TYPES){
        console.log("Trying to fetch instrument types for the given exchange..");
        if (param.exchange==null) {
            throw "Invalid Parameter";
        }
        var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
        count++;
        LOCK_GET_INSTRUMENTS_TYPES=true;
        r(8,forceed_exit_time);
        if(Authenticated) {
            instrument_types=null;
            setTimeout(function(){
            GetInstrumentTypes(param);
            ws.onmessage=function(e){
                if(e!=null){
                    if(e.data.includes('"MessageType":"'+constants.MESSAGE_INSTRUMENT_TYPES_RESULT+'"') ){
                        console.log(e.data);
                        instrument_types=e.data;
                        count--;
                        LOCK_GET_INSTRUMENTS_TYPES=false;
                        if(callback)
                           callback(instrument_types);
                    }
                 }
            };
        },(count>0)?getSynchronizationDelay(8):1);
        }
      }
    };
    /**
	 *Get the list of products for the given exchange
	 * @memberOf DhelmGfeed
	 * @method getProducts
     * @param {object} param 
     * @param {string} param.exchange The exchange.
     * @param {string} param.instrument_type The type of the instrument, e.g. NIFTY,GAIL etc(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getProducts=function(param,callback){
        if(!Authenticated)return;
    if(!LOCK_GET_PRODUCTS){
        console.log("Trying to fetch products for the given exchange..");
        if (param.exchange==null) {
            throw "Invalid Parameter";
        }
        var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
        count++;
        LOCK_GET_PRODUCTS=true;
        r(9,forceed_exit_time);
        if(Authenticated) {
            products=null;
            setTimeout(function(){
            GetProducts(param);
            ws.onmessage=function(e){
                if(e!=null){
                    if(e.data.includes('"MessageType":"'+constants.MESSAGE_PRODUCTS_RESULT+'"') ){
                        console.log(e.data);
                        products=e.data;
                        count--;
                        LOCK_GET_PRODUCTS=false;
                        if(callback)
                           callback(products);
                    }
                 }
            };
        },(count>0)?getSynchronizationDelay(9):1);
        }
    }
    };
    /**
	 * Get the list of expiry dates for different products for the given exchange
	 * @memberOf DhelmGfeed
	 * @method getExpiryDates
     * @param {object} param 
     * @param {string} param.exchange The exchange.
     * @param {string} param.instrument_type The type of the instrument, e.g. OPTIDX,FUTIDX etc(optional).
     * @param {string} param.product The product, e.g. NIFTY,BANKNIFTY etc(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getExpiryDates=function(param,callback){
        if(!Authenticated)return;
    if(!LOCK_GET_EXPIRY){
        console.log("Trying to fetch the expiry dates for different products..");
        if (param.exchange==null) {
            throw "Invalid Parameter";
        }
        var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
        count++;
        LOCK_GET_EXPIRY=true;
        r(10,forceed_exit_time);
        if(Authenticated) {
            expiry_dates=null;
            setTimeout(function(){
            GetExpiryDates(param);
            ws.onmessage=function(e){
                if(e!=null){
                    if(e.data.includes('"MessageType":"'+constants.MESSAGE_EXPIRY_DATE_RESULT+'"') ){
                        console.log(e.data);
                        expiry_dates=e.data;
                        count--;
                        LOCK_GET_EXPIRY=false;
                        if(callback)
                           callback(expiry_dates);
                    }
                 }
            };
        },(count>0)?getSynchronizationDelay(10):1);
        }
    }
    };
     /**
	 * Get the list of option types  for the given exchange
	 * @memberOf DhelmGfeed
	 * @method getOptionTypes
     * @param {object} param 
     * @param {string} param.exchange The exchange.
     * @param {string} param.instrument_type The type of the instrument, e.g. OPTIDX,FUTIDX etc(optional).
     * @param {string} param.product The product, e.g. NIFTY,BANKNIFTY etc(optional).
     * @param {string} param.expiry The expiry date, e.g. 25OCT2018(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getOptionTypes=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_OPTION_TYPES){
            console.log("Trying to fetch the option types.");
            if (param.exchange==null) {
                throw "Invalid Parameter";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_OPTION_TYPES=true;
            r(11,forceed_exit_time);
            if(Authenticated) {
                option_types=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetOptionTypes(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_OPTION_TYPES_RESULT+'"') ){
                            console.log(e.data);
                            option_types=e.data;
                            count--;
                            LOCK_GET_OPTION_TYPES=false;
                            if(callback)
                               callback(option_types);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(11):1);
            }
        }
    };
    /**
	 * Get the list of strike prices   for the given exchange
	 * @memberOf DhelmGfeed
	 * @method getStrikePrices
     * @param {object} param 
     * @param {string} param.exchange The exchange.
     * @param {string} param.instrument_type The type of the instrument, e.g. OPTIDX,FUTIDX etc(optional).
     * @param {string} param.product The product, e.g. NIFTY,BANKNIFTY etc(optional).
     * @param {string} param.expiry The expiry date, e.g. 25OCT2018(optional).
     * @param {string} param.optiontype The option type, e.g. PE,CE(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getStrikePrices=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_STRIKE_PRICES){
            console.log("Trying to fetch the strike prices.");
            if (param.exchange==null) {
                throw "Invalid Parameter";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_STRIKE_PRICES=true;
            r(12,forceed_exit_time);
            if(Authenticated) {
                strike_prices=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetStrikePrices(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_STRIKE_PRICES_RESULT+'"') ){
                            console.log(e.data);
                            strike_prices=e.data;
                            count--;
                            LOCK_GET_STRIKE_PRICES=false;
                            if(callback)
                               callback(strike_prices);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(12):1);
            }
        }
    };
    /**
	 * Get limitations of your subscription plan
	 * @memberOf DhelmGfeed
	 * @method getLimitation
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getLimitation=function(callback){
        if(!Authenticated)return;
        if(!LOCK_GET_LIMITATION){
            console.log("Trying to fetch subscription details.");
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_LIMITATION=true;
            r(13,forceed_exit_time);
            if(Authenticated) {
                limitation=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetLimitation();
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_LIMITATION_RESULT+'"') ){
                            console.log(e.data);
                            limitation=e.data;
                            count--;
                            LOCK_GET_LIMITATION=false;
                            if(callback)
                               callback(limitation);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(13):1);
            }
        }
    };
    /**
	 * Get server information
	 * @memberOf DhelmGfeed
	 * @method getServerInfo
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getServerInfo=function(callback){
        if(!Authenticated)return;
        if(!LOCK_GET_SERVER_INFO){
            console.log("Trying to fetch server info.");
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_SERVER_INFO=true;
            r(14,forceed_exit_time);
            if(Authenticated) {
                server_info=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetServerInfo();
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_SERVER_INFO_RESULT+'"') ){
                            console.log(e.data);
                            server_info=e.data;
                            count--;
                            LOCK_GET_LIMITATION=false;
                            if(callback)
                               callback(server_info);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(14):1);
            }
        }
    };
    /**
	 * Get market message  for the given exchange
	 * @memberOf DhelmGfeed
	 * @method getMarketMessage
     * @param {object} param 
     * @param {string} param.exchange The exchange.
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getMarketMessage=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_MARKET_MESSAGE){
            console.log("Trying to fetch market message.");
            if (param.exchange==null) {
                throw "Invalid Parameter";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_MARKET_MESSAGE=true;
            r(15,forceed_exit_time);
            if(Authenticated) {
                market_message=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetMarketMessage(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_MARKET_MESSAGE_RESULT+'"') ){
                            console.log(e.data);
                            market_message=e.data;
                            count--;
                            LOCK_GET_MARKET_MESSAGE=false;
                            if(callback)
                               callback(market_message);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(15):1);
            }
        }
    };
    /**
	 * Get exchange message  for the given exchange
	 * @memberOf DhelmGfeed
	 * @method getExchangeMessage
     * @param {object} param 
     * @param {string} param.exchange The exchange.
     * @param {function} callback The callback function
	 * @instance
	 */
    this.getExchangeMessage=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_GET_EXCHANGE_MESSAGE){
            console.log("Trying to fetch exchange message.");
            if (param.exchange==null) {
                throw "Invalid Parameter";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_GET_EXCHANGE_MESSAGE=true;
            r(16,forceed_exit_time);
            if(Authenticated) {
                exchange_message=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetExchangeMessage(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_EXCHANGE_MESSAGE_RESULT+'"') ){
                            console.log(e.data);
                            exchange_message=e.data;
                            count--;
                            LOCK_GET_EXCHANGE_MESSAGE=false;
                            if(callback)
                               callback(exchange_message);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(16):1);
            }
        }
    };
    /**
	 * Subscribe to Realtime data, returns market data every tick.
	 * @memberOf DhelmGfeed
	 * @method subscribeRealTime
     * @param {object} param 
     * @param {string} param.exchange The exchange(required).
     * @param {string} param.instrument_identifier The instrument identifier(required).
     * @param {boolean} param.unsubscribe The default is false.Pass true to unsubscribe(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.subscribeRealTime=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_SUBSCRIBE_REALTIME){
            console.log("Subsribe/unsubscribe realtime data.");
            if (param.exchange==null) {
                throw "Invalid Parameter/exchange cannot be null.";
            }
            if (param.instrument_identifier==null) {
                throw "Invalid Parameter/instrument_identifier cannot be null.";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_SUBSCRIBE_REALTIME=true;
            r(17,forceed_exit_time);
            if(Authenticated) {
                real_time_result=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetRealTimeResult(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_REAL_TIME_RESULT+'"') ){
                            console.log(e.data);
                            real_time_result=e.data;
                            count--;
                            LOCK_SUBSCRIBE_REALTIME=false;
                            if(callback)
                               callback(real_time_result);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(17):1);
            }
        }
    };
    /**
	 * Subscribe to Realtime data, returns data at snapshot periodicity.
	 * @memberOf DhelmGfeed
	 * @method subscribeRealTimeSnapshot
     * @param {object} param 
     * @param {string} param.exchange The exchange(required).
     * @param {string} param.instrument_identifier The instrument identifier(required).
     * @param {string} param.periodicity The peridocity.Valid value is either "MINUTE" or "HOUR"(required).
     * @param {boolean} param.unsubscribe The default is false.Pass true to unsubscribe(optional).
     * @param {function} callback The callback function
	 * @instance
	 */
    this.subscribeRealTimeSnapshot=function(param,callback){
        if(!Authenticated)return;
        if(!LOCK_SUBSCRIBE_REALTIME_SNAPSHOT){
            console.log("Subsribe/unsubscribe realtime snapshot data.");
            if (param.exchange==null) {
                throw "Invalid Parameter/exchange cannot be null.";
            }
            if (param.instrument_identifier==null) {
                throw "Invalid Parameter/instrument_identifier cannot be null.";
            }
            if (param.periodicity==null) {
                throw "Invalid Parameter/periodicity cannot be null .";
            }
            if(param.periodicity!=constants.HOUR && param.periodicity!=constants.MINUTE){
                throw "The value for periodicity is invalid";
            }
            var forceed_exit_time=Date.now()+FORCED_EXIT_TIMEOUT;        
            count++;
            LOCK_SUBSCRIBE_REALTIME_SNAPSHOT=true;
            r(18,forceed_exit_time);
            if(Authenticated) {
                real_time_snapshot_result=constants.RESULT_NOT_PREPARED;
                setTimeout(function(){
                GetRealTimeSnapshotResult(param);
                ws.onmessage=function(e){
                    if(e!=null){
                        if(e.data.includes('"MessageType":"'+constants.MESSAGE_REAL_TIME_SNAPSHOT_RESULT+'"') ){
                            console.log(e.data);
                            real_time_snapshot_result=e.data;
                            count--;
                            LOCK_SUBSCRIBE_REALTIME_SNAPSHOT=false;
                            if(callback)
                               callback(real_time_snapshot_result);
                        }
                     }
                };
            },(count>0)?getSynchronizationDelay(18):1);
            }
        }
    };
    /**
     * Set auto reconnection status.
	 * @memberOf DhelmGfeed
	 * @method setAutoReconnectStatus
     * @param {boolean} isTrue Auto reconnection status will be true if set true, else false. 
     */
    this.setAutoReconnectStatus=function(isTrue){
       if(isTrue!=null){
           if(isTrue==true || isTrue==false)auto_reconnect=isTrue;
       }
    }
    /**
     * Set multiplier value to increase delay.
	 * @memberOf DhelmGfeed
	 * @method setMultiplier
     * @param {number}value multiplier Multiplier value. 
     */
    this.setMultiplier=function(value){
        if(value!=null){
            MULTIPLIER=value;
        }
     }
     /**
     * Set synchronization delay.
	 * @memberOf DhelmGfeed
	 * @method setSynchronizationDelay
     * @param {number} value delay value. 
     */
    this.setSynchronizationDelay=function(value){
        if(value!=null){
            TIMEOUT=value;
        }
     }
    /**
     * Set function release time.
	 * @memberOf DhelmGfeed
	 * @method setFunctionReleaseTime
     * @param {number} value function release value. 
     */
    this.setFunctionReleaseTime=function(value){
        if(value!=null){
            FORCED_EXIT_TIMEOUT=value;
        }
     }
    
    //
    function onDisconnect(e) {
		ws = null;
		if(auto_reconnect) attemptReconnection();
    }
    //
    var current_reconnection_count=0;
    var reconnect_max_tries=10;
    var last_reconnect_interval=0;
    var reconnect_max_delay=3000;
    function attemptReconnection() {
        console.log("***TRYING TO RECONNECT******");
        if(current_reconnection_count > reconnect_max_tries) {
            console.log("***RECONNECTION FAILED******");
			process.exit(1);
        }
        if (current_reconnection_count > 0) {
			last_reconnect_interval = Math.pow(2, current_reconnection_count);
		} else if (!last_reconnect_interval) {
			last_reconnect_interval = 1;
		}

		if (last_reconnect_interval > reconnect_max_delay) {
			last_reconnect_interval = reconnect_max_delay;
		}

		current_reconnection_count++;

		reconnect_timer = setTimeout(function() {
			self.connect();
        }, last_reconnect_interval * 1000);

    }
    //
    function Authenticate() {
        console.log("Trying to authenticate");		
        if (ws.OPEN==1) {
            strMessage = '{"MessageType":"'+constants.AUTHENTICATE+'","Password":"' + api_key + '"}';
            if(!Authenticated)
			   callAPI(strMessage);
        }
    }
    //
    function GetSubscribedExchanges(){        
        if (ws.OPEN==1) {
            var strMessage = {MessageType: constants.GET_EXCHANGES};
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetInstrumentsOnSearch(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_INSTRUMENTS_ON_SEARCH,
                Exchange: param.exchange,
                Search: param.search_word};
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetInstruments(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_INSTRUMENTS};
            if(param.exchange!=null)
            strMessage.Exchange= param.exchange;
            if(param.instrument_type!=null)
            strMessage.InstrumentType= param.instrument_type;
            if(param.product!=null)
            strMessage.Product= param.product;
            if(param.expiry!=null)
            strMessage.Expiry= param.expiry;
            if(param.optiontype!=null)
            strMessage.OptionType= param.optiontype;
            if(param.strikeprice!=null)
            strMessage.StrikePrice=param.strikeprice;
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetLastQuote(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_LAST_QUOTE,
                          Exchange: param.exchange,
                          InstrumentIdentifier: param.instrument_identifier};
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetLastQuoteArray(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_LAST_QUOTE_ARRAY,
                          Exchange: param.exchange
                          };
            var list=[];
            for (var i = 0; i < param.instrument_identifiers.length; i++) {
                var item={};
                item.Value=param.instrument_identifiers[i];
                list.push(item);
            }
            strMessage.InstrumentIdentifiers=list;
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetSnapshot(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_SNAPSHOT,
                          Exchange: param.exchange
                          };
            var list=[];
            for (var i = 0; i < param.instrument_identifiers.length; i++) {
                var item={};
                item.Value=param.instrument_identifiers[i];
                list.push(item);
            }
            strMessage.InstrumentIdentifiers=list;
            if(param.periodicity!=null)
            strMessage.Periodicity=param.periodicity;
            if(param.period!=null)
            strMessage.Period=param.period;
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetHistoricalTick(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_HISTORY,
                              Exchange:param.exchange,
                              InstrumentIdentifier:param.instrument_identifier,
                              Periodicity:constants.TICK,
                              From:param.from,
                              To:param.to};
            if(param.max!=null){
             strMessage.Max=param.max;
            }
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetHistoricalOHLC(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_HISTORY,
                              Exchange:param.exchange,
                              InstrumentIdentifier:param.instrument_identifier,
                              Periodicity:param.periodicity,
                              From:param.from,
                              To:param.to};
            if(param.max!=null){
             strMessage.Max=param.max;
            }
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetInstrumentTypes(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_INSTRUMENT_TYPES,
                          Exchange:param.exchange};
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
     //
     function GetProducts(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_PRODUCTS,
                          Exchange: param.exchange};
            if(param.instrument_type!=null)
            strMessage.InstrumentType= param.instrument_type;
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetExpiryDates(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_EXPIRY_DATES,
                          Exchange: param.exchange};
            if(param.instrument_type!=null)
            strMessage.InstrumentType= param.instrument_type;
            if(param.product!=null)
            strMessage.Product= param.product;
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetOptionTypes(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_OPTION_TYPES,
                          Exchange: param.exchange};
            if(param.instrument_type!=null)
            strMessage.InstrumentType= param.instrument_type;
            if(param.product!=null)
            strMessage.Product= param.product;
            if(param.expiry!=null)
            strMessage.Expiry= param.expiry;
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetStrikePrices(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_STRIKE_PRICES,
                          Exchange: param.exchange};
            if(param.instrument_type!=null)
            strMessage.InstrumentType= param.instrument_type;
            if(param.product!=null)
            strMessage.Product= param.product;
            if(param.expiry!=null)
            strMessage.Expiry= param.expiry;
            if(param.optiontype!=null)
            strMessage.OptionType= param.optiontype;
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
     //
     function GetLimitation(){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_LIMITATIONS,};
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetServerInfo(){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_SERVER_INFO,};
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetMarketMessage(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_MARKET_MESSAGE,
                          Exchange: param.exchange};
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetExchangeMessage(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.GET_EXCHANGE_MESSAGE,
                          Exchange: param.exchange};
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetRealTimeResult(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.SUBSCRIBE_REAL_TIME,
                          Exchange: param.exchange,
                          InstrumentIdentifier: param.instrument_identifier};
            if(param.unsubscribe!=null)
            strMessage.Unsubscribe= param.unsubscribe;
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function GetRealTimeSnapshotResult(param){
        if (ws.OPEN==1) {
            var strMessage = {MessageType:constants.SUBSCRIBE_SNAPSHOT,
                              Exchange: param.exchange,
                              InstrumentIdentifier: param.instrument_identifier,
                              Periodicity:param.periodicity
                          };
            if(param.unsubscribe!=null)
            strMessage.Unsubscribe= param.unsubscribe;
            if(Authenticated){
               callAPI(JSON.stringify(strMessage));
             }
        }
    }
    //
    function callAPI(request){
		console.log("request: *****" + request + "*****");
		if (ws.OPEN) {
            ws.send(request);
        }
    }
    //
    function  getSynchronizationDelay(instance_no){
      if(previous_call==3|| previous_call==7.1 || previous_call==7.2){
        if(Date.now()<SYNCHRONIZATION_EXP){
            fn_call_log(instance_no);
            return ((SYNCHRONIZATION_EXP=SYNCHRONIZATION_EXP+MULTIPLIER*TIMEOUT)-Date.now());
        }
        else{
            fn_call_log(instance_no);
            return ((SYNCHRONIZATION_EXP=Date.now()+MULTIPLIER*TIMEOUT)-Date.now());
        } 
      }
      if(Date.now()<SYNCHRONIZATION_EXP){
          fn_call_log(instance_no);
          return ((SYNCHRONIZATION_EXP=SYNCHRONIZATION_EXP+TIMEOUT)-Date.now());
      }
      else{
          fn_call_log(instance_no);
          return ((SYNCHRONIZATION_EXP=Date.now()+TIMEOUT)-Date.now());
      }
    }
    //
    function fn_call_log(instance_no){
         if(count==0)previous_call=-1;
         else previous_call=instance_no;
    }
    //Function to release an requested resource on predefined time expiration
    function r(fnIndex,forceed_exit_time){
       // console.log("*****************CLOCK STARTED*************************");
        setTimeout(function(){
           if(fnIndex==1 && LOCK_GET_EXCHANGES)LOCK_GET_EXCHANGES=false;
           else if(fnIndex==2 && LOCK_GET_INSTRUMENTS_ON_SEARCH)LOCK_GET_INSTRUMENTS_ON_SEARCH=false;
           else if(fnIndex==3 && LOCK_GET_INSTRUMENTS)LOCK_GET_INSTRUMENTS=false;
           else if(fnIndex==4 && LOCK_GET_LAST_QUOTE)LOCK_GET_LAST_QUOTE=false;
           else if(fnIndex==5 && LOCK_GET_LAST_QUOTE_ARRAY)LOCK_GET_LAST_QUOTE_ARRAY=false;
           else if(fnIndex==6 && LOCK_GET_SNAPSHOT)LOCK_GET_SNAPSHOT=false;
           else if(fnIndex==7.1 && LOCK_GET_HISTORY_TICK)LOCK_GET_HISTORY_TICK=false;
           else if(fnIndex==7.2 && LOCK_GET_HISTORY_OHLC)LOCK_GET_HISTORY_OHLC=false;
           else if(fnIndex==8 &&LOCK_GET_INSTRUMENTS_TYPES)LOCK_GET_INSTRUMENTS_TYPES=false;
           else if(fnIndex==9 && LOCK_GET_PRODUCTS)LOCK_GET_PRODUCTS=false;
           else if(fnIndex==10 && LOCK_GET_EXPIRY)LOCK_GET_EXPIRY=false;
           else if(fnIndex==11 && LOCK_GET_OPTION_TYPES)LOCK_GET_OPTION_TYPES=false;
           else if(fnIndex==12 && LOCK_GET_STRIKE_PRICES)LOCK_GET_STRIKE_PRICES=false;
           else if(fnIndex==13 && LOCK_GET_LIMITATION)LOCK_GET_LIMITATION=false;
           else if(fnIndex==14 && LOCK_GET_SERVER_INFO)LOCK_GET_SERVER_INFO=false;
           else if(fnIndex==15 && LOCK_GET_MARKET_MESSAGE)LOCK_GET_MARKET_MESSAGE=false;
           else if(fnIndex==16 && LOCK_GET_EXCHANGE_MESSAGE)LOCK_GET_EXCHANGE_MESSAGE=false;
           else if(fnIndex==17 && LOCK_SUBSCRIBE_REALTIME)LOCK_SUBSCRIBE_REALTIME=false;
           else if(fnIndex==18 && LOCK_SUBSCRIBE_REALTIME_SNAPSHOT)LOCK_SUBSCRIBE_REALTIME_SNAPSHOT=false;
        },forceed_exit_time-Date.now());
   }
   var self=this;
};
module.exports = DhelmGfeed;