API Docs for:
Show:

File: msoDriver/index.js

'use strict';
/**
*   Module use to communicate with GWINSTEK's DSO through Ethernet or USB
*
*   @module instrument-com
*/
var net     = require('net');
var fs      = require('fs');
var async   = require('async');
var uitl    = require('util');
var events  = require('events');
var path    = require('path');

var debug = require('debug');
var log = debug('index:log');
var info = debug('index:info');
var error = debug('index:error');
var sytConstant=require('./sysConstant.js');
var syscmd = require('./system.js');
var trigcmd = require('./trigger.js');
var acqcmd = require('./acquire.js');
var horcmd = require('./horizontal.js');
var mathcmd = require('./math.js');
var meascmd = require('./measure.js');
var channel = require('./channel.js');
    // usbDev = require('./devUsb.js');
var usbDev = require('./devUsbFs.js');
var supportType = ['GDS2000E'];
//

var chanLoadCmd = [
        [   {id:'ch1',prop:'ChState',arg:'',cb:null,method:'get'},
            {id:'ch1',prop:'BWLimit',arg:'',cb:null,method:'get'},
            {id:'ch1',prop:'COUPling',arg:'',cb:null,method:'get'},
            {id:'ch1',prop:'VerSCALe',arg:'',cb:null,method:'get'},
            {id:'ch1',prop:'VerPOSition',arg:'',cb:null,method:'get'},
            {id:'ch1',prop:'VerEXPand',arg:'',cb:null,method:'get'},
            {id:'ch1',prop:'INVert',arg:'',cb:null,method:'get'},
            {id:'ch1',prop:'PROBe_RATio',arg:'',cb:null,method:'get'},
            {id:'ch1',prop:'PROBe_Type',arg:'',cb:null,method:'get'},
            {id:'ch1',prop:'DESKew',arg:'',cb:null,method:'get'}
        ],[
            {id:'ch2',prop:'ChState',arg:'',cb:null,method:'get'},
            {id:'ch2',prop:'BWLimit',arg:'',cb:null,method:'get'},
            {id:'ch2',prop:'COUPling',arg:'',cb:null,method:'get'},
            {id:'ch2',prop:'VerSCALe',arg:'',cb:null,method:'get'},
            {id:'ch2',prop:'VerPOSition',arg:'',cb:null,method:'get'},
            {id:'ch2',prop:'VerEXPand',arg:'',cb:null,method:'get'},
            {id:'ch2',prop:'INVert',arg:'',cb:null,method:'get'},
            {id:'ch2',prop:'PROBe_RATio',arg:'',cb:null,method:'get'},
            {id:'ch2',prop:'PROBe_Type',arg:'',cb:null,method:'get'},
            {id:'ch2',prop:'DESKew',arg:'',cb:null,method:'get'}
        ],[
            {id:'ch3',prop:'BWLimit',arg:'',cb:null,method:'get'},
            {id:'ch3',prop:'COUPling',arg:'',cb:null,method:'get'},
            {id:'ch3',prop:'VerSCALe',arg:'',cb:null,method:'get'},
            {id:'ch3',prop:'VerPOSition',arg:'',cb:null,method:'get'},
            {id:'ch3',prop:'VerEXPand',arg:'',cb:null,method:'get'},
            {id:'ch3',prop:'INVert',arg:'',cb:null,method:'get'},
            {id:'ch3',prop:'PROBe_RATio',arg:'',cb:null,method:'get'},
            {id:'ch3',prop:'PROBe_Type',arg:'',cb:null,method:'get'},
            {id:'ch3',prop:'DESKew',arg:'',cb:null,method:'get'}
        ],[
            {id:'ch4',prop:'ChState',arg:'',cb:null,method:'get'},
            {id:'ch4',prop:'BWLimit',arg:'',cb:null,method:'get'},
            {id:'ch4',prop:'COUPling',arg:'',cb:null,method:'get'},
            {id:'ch4',prop:'VerSCALe',arg:'',cb:null,method:'get'},
            {id:'ch4',prop:'VerPOSition',arg:'',cb:null,method:'get'},
            {id:'ch4',prop:'VerEXPand',arg:'',cb:null,method:'get'},
            {id:'ch4',prop:'INVert',arg:'',cb:null,method:'get'},
            {id:'ch4',prop:'PROBe_RATio',arg:'',cb:null,method:'get'},
            {id:'ch4',prop:'PROBe_Type',arg:'',cb:null,method:'get'},
            {id:'ch4',prop:'DESKew',arg:'',cb:null,method:'get'}
        ]
    ];
var trigLoadCmd = [
        {id:'trig',prop:'TrigType',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigSource',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigHighLevel',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigLowLevel',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigEdgeSlop',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigCouple',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigNoiseRej',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigMode',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigHoldoff',arg:'',cb:null,method:'get'},

        {id:'trig',prop:'TrigType',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigDelayType',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigDelayEvent',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigDelayType',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigDelaySlop',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigDelayLevel',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigDelayTime',arg:'',cb:null,method:'get'},

    // {id:'trig',prop:'TrigPulseWidthPolarity',arg:'NEGATIVE'},
    // {id:'trig',prop:'TrigPulseWidthWhen',arg:'EQUAL'},
    // {id:'trig',prop:'TrigPulseWidthTime',arg:'1E-1'},
    // {id:'trig',prop:'TrigRuntPolarity',arg:'EITHER'},
    // {id:'trig',prop:'TrigRuntWhen',arg:'UNEQUAL'},
    // {id:'trig',prop:'TrigRuntTime',arg:'1E-1'},
    // {id:'trig',prop:'TrigRiseFallSlop',arg:'EITHER'},
    // {id:'trig',prop:'TrigRiseFallWhen',arg:'LESSTHAN'},
    // {id:'trig',prop:'TrigRiseFallTime',arg:'1E-1'},
    // {id:'trig',prop:'TrigVideoType',arg:'NTSC'},
    // {id:'trig',prop:'TrigVideoField',arg:'FIELD2'},
    // {id:'trig',prop:'TrigVideoLine',arg:'262'},
    // {id:'trig',prop:'TrigVideoPolarity',arg:'NEGATIVE'},
    // {id:'trig',prop:'TrigALT',arg:'OFF'},
    // {id:'trig',prop:'TrigExtProbeType',arg:'CURRENT'},
    // {id:'trig',prop:'TrigExtProbeRatio',arg:'1E+0'},
        {id:'trig',prop:'TrigType',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigTimeoutTime',arg:'',cb:null,method:'get'},
        {id:'trig',prop:'TrigTimeoutWhen',arg:'',cb:null,method:'get'}
    ];
var acqLoadCmd = [
        {id:'acq',prop:'AcqRecLength',arg:'',cb:null,method:'get'},
        {id:'acq',prop:'AcqMode',arg:'',cb:null,method:'get'},
        {id:'acq',prop:'AcqAverage',arg:'',cb:null,method:'get'}
    ];
var horLoadCmd = [
        {id:'hor',prop:'HorMode',arg:'',cb:null,method:'get'},
        {id:'hor',prop:'HorScale',arg:'',cb:null,method:'get'},
        {id:'hor',prop:'HorPosition',arg:'',cb:null,method:'get'},
        {id:'hor',prop:'HorExpand',arg:'',cb:null,method:'get'},
        {id:'hor',prop:'HorMode',arg:'',cb:null,method:'get'},
        {id:'hor',prop:'HorZoomScale',arg:'',cb:null,method:'get'},
        {id:'hor',prop:'HorZoomPosition',arg:'',cb:null,method:'get'}
    ];
var mathLoadCmd = [
        {id:'math',prop:'MathDisp',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathType',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathDualSour1',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathDualSour2',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathDualOper',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathDualScale',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathDualPos',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathType',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathFftWin',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathFftSource',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathFftMag',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathFftVerPos',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathFftVerScale',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathFftHorPos',arg:'',cb:null,method:'get'},
        {id:'math',prop:'MathFftHorScale',arg:'',cb:null,method:'get'}

        // {id:'meas1',prop:'MeasureState',arg:'ON'},
        // {id:'meas1',prop:'StatisticMode',arg:'ON'},
        // //{id:'meas1',prop:'StatisticReset',arg:''},
        // {id:'meas1',prop:'MeasureSource1',arg:'CH1'},
        // {id:'meas1',prop:'MeasureSource2',arg:'CH2'},
        // {id:'meas1',prop:'MeasureType',arg:'PK2pk'},
    ];
var trigTestCmd = [
        {prop:'TrigType',arg:'EDGE'},
        {prop:'TrigSource',arg:'CH2'},
        {prop:'TrigHighLevel',arg:'1E-1'},
        {prop:'TrigLowLevel',arg:'2E-1'},
        {prop:'TrigEdgeSlop',arg:'RISE'},
        {prop:'TrigCouple',arg:'AC'},
        {prop:'TrigNoiseRej',arg:'ON'},
        {prop:'TrigMode',arg:'NORMAL'},
        {prop:'TrigHoldoff',arg:'1E-1'},

        {prop:'TrigType',arg:'DELAY'},
        {prop:'TrigDelayType',arg:'EVENT'},
        {prop:'TrigDelayEvent',arg:'1100'},
        {prop:'TrigDelayType',arg:'TIME'},
        {prop:'TrigDelaySlop',arg:'FALL'},
        {prop:'TrigDelayLevel',arg:'1E-1'},
        {prop:'TrigDelayTime',arg:'1E-1'},

        // {prop:'TrigPulseWidthPolarity',arg:'NEGATIVE'},
        // {prop:'TrigPulseWidthWhen',arg:'EQUAL'},
        // {prop:'TrigPulseWidthTime',arg:'1E-1'},
        // {prop:'TrigRuntPolarity',arg:'EITHER'},
        // {prop:'TrigRuntWhen',arg:'UNEQUAL'},
        // {prop:'TrigRuntTime',arg:'1E-1'},
        // {prop:'TrigRiseFallSlop',arg:'EITHER'},
        // {prop:'TrigRiseFallWhen',arg:'LESSTHAN'},
        // {prop:'TrigRiseFallTime',arg:'1E-1'},
        // {prop:'TrigVideoType',arg:'NTSC'},
        // {prop:'TrigVideoField',arg:'FIELD2'},
        // {prop:'TrigVideoLine',arg:'262'},
        // {prop:'TrigVideoPolarity',arg:'NEGATIVE'},
        // {prop:'TrigALT',arg:'OFF'},
        // {prop:'TrigExtProbeType',arg:'CURRENT'},
        // {prop:'TrigExtProbeRatio',arg:'1E+0'},
        {prop:'TrigType',arg:'TIMEOUT'},
        {prop:'TrigTimeoutTime',arg:'1E+0'},
        {prop:'TrigTimeoutWhen',arg:'EITHER'}
    ];
var chTestCmd = [
        {prop:'ChState',arg:'ON'},
        {prop:'BWLimit',arg:'2E+7'},
        {prop:'COUPling',arg:'AC'},
        {prop:'VerSCALe',arg:'2E-1'},
        {prop:'VerPOSition',arg:'2E-1'},
        {prop:'VerEXPand',arg:'CENTER'},
        {prop:'INVert',arg:'ON'},
        {prop:'PROBe_RATio',arg:'1E+1'},
        {prop:'PROBe_Type',arg:'VOLTAGE'},
        {prop:'DESKew',arg:'0'}
    ];
var acqTestCmd = [
        {prop:'AcqRecLength',arg:'1E+5'},
        {prop:'AcqMode',arg:'AVERAGE'},
        {prop:'AcqAverage',arg:'16'}
    ];
var horTestCmd = [
        {prop:'HorMode',arg:'MAIN'},
        {prop:'HorScale',arg:'5E-5'},
        {prop:'HorPosition',arg:'5E-5'},
        {prop:'HorExpand',arg:'TRIGGER'},
        {prop:'HorMode',arg:'WINDOW'},
        {prop:'HorZoomScale',arg:'2E-5'},
        {prop:'HorZoomPosition',arg:'2E-5'}
    ];
var mathTestCmd = [
        {prop:'MathDisp',arg:'ON'},
        {prop:'MathType',arg:'DUAL'},
        {prop:'MathDualSour1',arg:'CH2'},
        {prop:'MathDualSour2',arg:'CH1'},
        {prop:'MathDualOper',arg:'DIV'},
        {prop:'MathDualScale',arg:'1'},
        {prop:'MathDualPos',arg:'1'},
        {prop:'MathType',arg:'FFT'},
        {prop:'MathFftWin',arg:'HAMMING'},
        {prop:'MathFftSource',arg:'CH2'},
        {prop:'MathFftMag',arg:'DB'},
        {prop:'MathFftVerPos',arg:'1'},
        {prop:'MathFftVerScale',arg:'1'},
        {prop:'MathFftHorPos',arg:'1'},
        {prop:'MathFftHorScale',arg:'1'}
    ];
var measSetTestCmd = [
        {prop:'MeasureState',arg:'ON'},
        {prop:'StatisticMode',arg:'ON'},
        {prop:'StatisticReset',arg:''},
        {prop:'MeasureSource1',arg:'CH1'},
        {prop:'MeasureSource2',arg:'CH2'},
        {prop:'MeasureType',arg:'PK2pk'}

    ];
var measGetTestCmd = [
        {prop:'MeasureValue',arg:'ON'},
        {prop:'MeasureStd',arg:''},
        {prop:'MeasureMin',arg:'CH2'},
        {prop:'MeasureMean',arg:'CH1'},
        {prop:'MeasureType',arg:'PK2pk'},
        {prop:'MeasureMax',arg:'ON'}

    ];
var dispTestCmd = [
        {prop:'DispOut',arg:''}
    ];
var sysTestCmd = [
        {prop:'SysErr',arg:''}
    ];



function show_props(obj, objName) {
    var obj_string = '';

    for (var i in obj) {
        if (typeof obj[i] === 'object'){
            obj_string += show_props(obj[i],i.toString());
        }else{
            obj_string += objName + '.' + i + '=' + obj[i] + '\n';
        }
    }

    return obj_string;
}

function getIDN(dsoObj, data, cb) {
    var id = data.toString().split(',');

    dsoObj.gdsType = '';
    for (var j = 0; j < supportType.length; j++) {
        var gdsModel = dsoObj.commandObj[supportType[j]].model;
        for (var i = 0; i < gdsModel.length ; i++) {
            log('compare ' + id[1] + 'with ' + gdsModel[i]);
            if (id[1] === gdsModel[i]) {
                dsoObj.gdsType = supportType[j];
                dsoObj.gdsModel = id[1];
                dsoObj.maxChNum = dsoObj.commandObj[supportType[j]].maxChNum[gdsModel[i]];
                break;
            }
        }
    }

    log('gdsType=' + dsoObj.gdsType);
    log('gdsModel=' + dsoObj.gdsModel);

    //cb(null,data);
    return true;
}

function getChInfo(dsoObj, data, cb) {
        log(data);
        cb(null, data);
}

function done(){
    log('------------------------- done');
}



function testDsoCmd(dsoObj, callback) {
    var tmp={};


    async.series(
        [
            function(done) {
                log('write command to server');
                dsoObj.state.conn = 'query';
                dsoObj.cmdHandler = getIDN;
                dsoObj.handlerSelf = dsoObj;
                dsoObj.syncCallback = done;
                dsoObj.write('*idn?\r\n');
                // dsoObj.net.socket.once('data',function(data){
                //     getIDN(data,dsoObj,done);
                // });

            },
            function(done) {
                dsoObj.state.conn = 'query';
                dsoObj.cmdHandler = getChInfo;
                dsoObj.handlerSelf = dsoObj;
                dsoObj.syncCallback = done;
                dsoObj.write(':CHANnel1:SCAle?\r\n');
                // dsoObj.net.socket.once('data',function(data){
                //     getChInfo(data,dsoObj,done);
                // });
            },
            // function(done){
            //     async.eachSeries(chTestCmd,
            //         function(item,done){
            //             dsoObj.ch1.getProp(item.prop,item.arg,done);

            //         },function(err,results){
            //             log('--------- Channel-1 Get Prop Test Cmd -------------');
            //             log('err:'+err);
            //             log('results:'+results);
            //             log('--------------------------------------------');
            //             done();
            //         }
            //     );
            // },
            // function(done){
            //     // dsoObj.ch2.getProp('ChState',tmp,done);
            //     async.eachSeries(chTestCmd,
            //         function(item,done){
            //             dsoObj.ch2.setProp(item.prop,item.arg,done);

            //         },function(err,results){
            //             log('--------- Channel-2 Set Prop Test Cmd -------------');
            //             log('err:'+err);
            //             log('results:'+results);
            //             log('--------------------------------------------');
            //             done();
            //         }
            //     );
            // },
            // function(done){
            //     async.eachSeries(sysTestCmd,
            //         function(item,done){
            //             dsoObj.sys.prop.get(item.prop,item.arg,done);
            //         },function(err,results){
            //             log('*************** System Get Error After Channel Test Cmd ***************');
            //             done();
            //         }
            //     );
            // },
            // function(done){
            //     async.eachSeries(acqTestCmd,
            //         function(item,done){
            //             dsoObj.acq.prop.set(item.prop,item.arg,done);

            //         },function(err,results){
            //             log('--------- Acquire Set Prop Test Cmd -------------');
            //             log('err:'+err);
            //             log('results:'+results);
            //             log('--------------------------------------------');
            //             done();
            //         }
            //     );
            // },
            // function(done){
            //     async.eachSeries(sysTestCmd,
            //         function(item,done){
            //             dsoObj.sys.prop.get(item.prop,item.arg,done);
            //         },function(err,results){
            //             log('*************** System Get Error After Acquire Test Cmd ***************');
            //             done();
            //         }
            //     );
            // },
            // function(done){
            //     async.eachSeries(horTestCmd,
            //         function(item,done){
            //             dsoObj.hor.prop.set(item.prop,item.arg,done);

            //         },function(err,results){
            //             log('--------- Horizontal Set Prop Test Cmd -------------');
            //             log('err:'+err);
            //             log('results:'+results);
            //             log('--------------------------------------------');
            //             done();
            //         }
            //     );
            // },
            // function(done){
            //     async.eachSeries(sysTestCmd,
            //         function(item,done){
            //             dsoObj.sys.prop.get(item.prop,item.arg,done);
            //         },function(err,results){
            //             log('*************** System Get Error After Horizontal Test Cmd ***************');
            //             done();
            //         }
            //     );
            // },
            // function(done){
            //     async.eachSeries(mathTestCmd,
            //         function(item,done){
            //             dsoObj.math.prop.set(item.prop,item.arg,done);

            //         },function(err,results){
            //             log('--------- Math Set Prop Test Cmd -------------');
            //             log('err:'+err);
            //             log('results:'+results);
            //             log('--------------------------------------------');
            //             done();
            //         }
            //     );
            // },
            // function(done){
            //     async.eachSeries(sysTestCmd,
            //         function(item,done){
            //             dsoObj.sys.prop.get(item.prop,item.arg,done);
            //         },function(err,results){
            //             log('*************** System Get Error After Horizontal Test Cmd ***************');
            //             done();
            //         }
            //     );
            // },
            function(done) {
                async.eachSeries(measSetTestCmd,
                    function(item,done) {
                        dsoObj.meas1.prop.set(item.prop, item.arg, done);

                    },function(err, results) {
                        log('--------- Measure1 Set Prop Test Cmd -------------');
                        log('err:' + err);
                        log('results:' + results);
                        log('--------------------------------------------');
                        done();
                    }
                );
            },

            function(done){
                async.eachSeries(measGetTestCmd,
                    function(item, done) {
                        dsoObj.meas1.prop.get(item.prop, item.arg, done);

                    },function(err, results) {
                        log('--------- Measure1 Get Prop Test Cmd -------------');
                        log('err:' + err);
                        log('results:' + results);
                        log('--------------------------------------------');
                        done();
                    }
                );
            },




            function(done) {
                async.eachSeries(trigTestCmd,
                    function(item, done) {
                        dsoObj.trig.prop.set(item.prop, item.arg, done);

                    },function(err, results) {
                        log('--------- Trigger Set Prop Test Cmd -------------');
                        log('err:' + err);
                        log('results:' + results);
                        log('--------------------------------------------');
                        done();
                    }
                );
            },
            function(done) {

                async.eachSeries(sysTestCmd,
                //async.eachSeries(dispTestCmd,
                    function(item, done) {
                        dsoObj.sys.prop.get(item.prop, item.arg, done);
                    },function(err, results){
                        log('*************** System Get Error After Trigger Test Cmd ***************');
                        done();
                    }
                );
            }
        ]
        ,
        function(err, results) {
            log('err:' + err);
            log('results:' + results);
            log('--------- dso object info -------------');
            if (typeof callback  === 'function')
                    callback();
        }
    );
};

// function sendIDN(){
// }
function checkDsoExist(dsoObj, callback) {
    var timeoutCnt = 0;
    log('checkDsoExist');
    log('write command to server');
    dsoObj.state.conn = 'query';
    dsoObj.cmdHandler = getIDN;
    dsoObj.handlerSelf = dsoObj;
    dsoObj.state.setTimeout = true;
    dsoObj.state.timeoutObj = setTimeout(function() {
        log('settimeout');
        dsoObj.state.conn = 'timeout';
        dsoObj.write('*idn?\r\n');
    }, 1000);
    dsoObj.write('*idn?\r\n');
    dsoObj.syncCallback = (function() {
        var self = this;

        if(timeoutCnt++ > 10) {
            callback('error');
        }

        if(this.gdsType ==='') {
            this.state.setTimeout = true;
            this.state.timeoutObj = setTimeout(function() {
                log('settimeout');
                self.state.conn = 'timeout';
                self.write('*idn?\r\n');
            }, 1000);
        }else {
            callback(null);
        }
    }).bind(dsoObj);


    // async.series(
    //     [
    //         function(done) {
    //             log('write command to server');
    //             dsoObj.state.conn='query';
    //             dsoObj.cmdHandler=getIDN;
    //             dsoObj.handlerSelf=dsoObj;
    //             dsoObj.syncCallback=done;
    //             dsoObj.write('*idn?\r\n');
    //         }
    //     ]
    //     ,
    //     function(err,results){
    //         dsoObj.state.conn='connected';
    //         log('err:'+err);
    //         log('results:'+results);
    //         log('--------- dso object info -------------');
    //         if(typeof callback  === 'function'){
    //                 callback();
    //                 return;
    //         }
    //     }
    // );
};
function enableSocketTime(dsoObj) {
    dsoObj.net.socket.setTimeout(1500,function() {
        log('socket timeout');
        if(dsoObj.state.conn === 'timeout') {
            dsoObj.net.socket.end();
            dsoObj.net.socket.destroy();
        }
    })
}
function enableInterfTime(dsoObj) {
    if(dsoObj.interf === 'net')
        enableSocketTime(dsoObj);
}
var Dso = function() {
    // dsoObj.state='connectting';
    this.state = {
        conn : 'disconnect',
        currentCmd : '',
        currentId : '',
        setTimeout : false,
        timeoutObj : {},
        errCode : {message:'', type:'', handler:function(){}}
    };
    // this.port=port;
    // this.host_addr=host_addr;
    this.interf = 'net';
    this.gdsType = '';
    this.gdsModel = '';
    this.chNum = 0;
    this.activeCh = '';
    this.cmdHandler = getIDN;
    this.handlerSelf = {};
    this.syncCallback = function(){};
    this.maxChNum = 0;
    this.commandObj = {};
    this.cmdSequence = [];
    this.writeTimeoutObj = null;
    this.asyncWrite = 'done';
    this.errHandler = function(){};
    this.write = function(data) {
        if (this.interf === 'usb') {
            this.usb.write(data);
        }else if (this.interf === 'net') {
            this.net.socket.write(data);
            return true;
        }
        // else
        //     return false;
        // return true;
    };
    this.dataHandler = (function(data) {
        if ((data === 0x0a) && (data.length === 1)) {
            log('receive one byte data');
            log(Number(data));
            log(data);
            log('=====================');
            return;
        }

        log('dataHandler receive ' + data.slice(0,11) + 'length=' + data.length);
        if (this.state.setTimeout) {
            // if(this.state.conn!=='timeout'){
                log('clearTimeout');
                clearTimeout(this.state.timeoutObj);
            // }
            this.state.setTimeout=false;
        }
        if (this.cmdHandler(this.handlerSelf, data,this.syncCallback) ===true) {
            if (typeof this.syncCallback === 'function') {
                log('call callback');
                this.syncCallback();
            }
        }
    }).bind(this);

}
uitl.inherits(Dso, events.EventEmitter);

Dso.prototype.GetSnapshot = function(cb) {
    this.sys.prop.get('DispOut', '', function() {
        if (cb){
            cb(this.sys.dispData);
        }
    });

}

Dso.prototype.GetRawdata = function(ch,cb) {
    var self = this;

    log(sytConstant.chID[ch]);

    if (sytConstant.chID[ch] !== undefined) {
        var cmd = [
                {id:'acq',prop:'AcqHeader',arg:'OFF',cb:done,method:'set'},
                {id:ch,prop:'AcqMemory',arg:'',cb:cb,method:'get'}
            ];
            this.emit('cmd_write',cmd);

            // async.eachSeries(cmd,
            //     function(item,done){
            //         log(item);
            //         if(item.id==='acq'){
            //             self.acq.prop.set(item.prop,item.arg,done);
            //         }
            //         else{
            //             self[ch].prop.get(item.prop,item.arg,done);
            //         }

            //     },function(err,results){
            //         if(cb)
            //             cb(self[ch].rawdata);
            //     }
            // );
    }else {
        if(cb){
            cb('error');
        }
    }

}

Dso.prototype.onSocketErr=function(cb) {
    var self = this;
    this.net.socket.on('error', function(e) {
        log('onTcpConnect: connect error!');
        self.state.conn = 'disconnect';
        self.net.socket.end();
        if (cb){
            cb(e.message);
        }
    });
}

Dso.prototype.GetPort = function(cb) {
    if (cb){
        cb(this.net.port);
    }else {
        return this.net.port;
    }
}

Dso.prototype.GetAddr = function(cb) {
    if(cb){
        cb(this.net.host_addr);
    }else {
        return this.net.host_addr;
    }
}



Dso.prototype.reloadState = function(cb) {
    var self = this;

    if(this.state.conn ==='disconnect') {
        cb('connection broken');
        return;
    }

    enableInterfTime(this);
    var reloadCmd = [].concat(trigLoadCmd);
    reloadCmd = reloadCmd.concat(acqLoadCmd);
    reloadCmd = reloadCmd.concat(horLoadCmd);
    async.series(
        [
            function(done) {
                async.eachSeries(reloadCmd,
                    function(item, done) {
                        self[item.id].prop.get(item.prop, item.arg,done);

                    },function(err, results) {
                        done();
                    }
                );
            },
            function(done) {
                var chCmd = [];
                for(var i = 0; i < self.maxChNum; i++) {
                    chCmd = chCmd.concat(chanLoadCmd[i]);
                }

                async.eachSeries(chCmd,
                    function(item, done) {
                            self[item.id].prop.get(item.prop, item.arg, done);

                    },function(err, results) {
                        done();
                    }
                );

            }
        ]
        ,
        function(err, results) {
            self.state.conn = 'connected';
            if (cb) {
                cb();
                return;
            }
        }
    );
};

function getCmdObj() {
    var FilePath = path.join(__dirname, '/command.json');

    this.commandObj = JSON.parse(fs.readFileSync(FilePath));
}
function BindNetObj(dsoObj, port, host_addr) {

    // dsoObj.port=port;
    // dsoObj.host_addr=host_addr;
    dsoObj.interf = 'net';
    dsoObj.net = {
        dataHandler : function(data) {
            // log('socket on data event!');

            // socket idle when send query command
            if (dsoObj.state.setTimeout) {
                if (dsoObj.state.conn !== 'timeout') {
                    log('clearTimeout');
                    clearTimeout(dsoObj.state.timeoutObj);
                }
                dsoObj.state.setTimeout = false;
            }

            if ((dsoObj.state.conn === 'query') || (dsoObj.state.conn === 'timeout')) {
                if (dsoObj.cmdHandler(dsoObj.handlerSelf, data, dsoObj.syncCallback) === true) {
                    if (dsoObj.syncCallback) {
                        log('call callback');
                        dsoObj.syncCallback();
                    }
                }
            }
        },
        port : port,
        host_addr : host_addr,
        socket : {}
    };
}
Dso.prototype.tcpConnect = function(Callback) {
    var err_string;
    var self = this;

    this.net.socket = net.connect( this.net.port, this.net.host_addr, function() { //'connect' listener
                      log('connected to server!');
                      //dsoObj.net.socket.setEncoding('utf8');
                      self.net.socket.setMaxListeners(0);
                      self.state.conn = 'connected';
                      self.interf = 'net';
                      // self.net.socket.on('data',self.net.dataHandler);
                      self.net.socket.on('data',self.dataHandler);
                      checkDsoExist(self,Callback);
                      // if(Callback)
                      //   Callback();
                });

            this.net.socket.on('close', function(e) {
            log('onTcpConnect: close!');
            self.state.conn = 'disconnect';
            err_string = e.message;
            //dsoObj.net.socket.destroy();
        });
};

Dso.prototype.usbConnect = function(Callback) {
    var err_string;
    var self = this;

    usbDev.openUsb(this, function() {
            // log(self.usb);
            // self.usb.onData(self.dataHandler);
            checkDsoExist(self, Callback);
    });
};
Dso.prototype.cmd_write = function(cmdSequence) {
    var self = this;
    var cb = null;

    var cmd = [];

    if (this.asyncWrite === 'busy') {
        log('async write busy');
        if (this.writeTimeoutObj === null) {
            log('set timeout');
            this.writeTimeoutObj = setTimeout(function() {
                log('cmd_write reissue');
                self.writeTimeoutObj = null;
                self.cmd_write(cmdSequence);
            },100);
        }
        return;
    }

    if (this.cmdSequence.length === 0) {
        if (this.writeTimeoutObj !== null) {
            clearTimeout(this.writeTimeoutObj);
            // this.writeTimeoutObj=null;
            this.emit('cmd_write', self.cmdSequence);
        }
        log('cmdSequence = 0');
        return;
    }

    for (var i = 0, len = this.cmdSequence.length; i < len; i++) {
        cmd[i] = this.cmdSequence.shift();

        if (cmd[i].cb !== null){// avoid missing async callback
            cb = cmd[i].cb;
                this.writeTimeoutObj = setTimeout(function() {
                    log('cmd_write reissue');
                    self.writeTimeoutObj = null;
                    self.cmd_write(cmdSequence);
                },100);
            break;
        }
    }
    self.asyncWrite = 'busy';
    async.eachSeries(cmd,
        function(item,done) {
            log(item);
            if(item.method === 'set') {
                self[item.id].prop.set(item.prop, item.arg, done);
            }else {
                self[item.id].prop.get(item.prop, item.arg, done);
            }
        },function(err, results) {
            self.asyncWrite = 'done';
            log('async write done');
            if (cb)
                cb(err);
        }
    );



}

/**
*   Create all needed private properties and method
*
*   @private
*   @constructor _DsoObj
*
*   @return {Object} Private method used to control DSO
*/
var _DsoObj = function() {

    var dsoObj = new Dso();

    getCmdObj.call(dsoObj);
    //assign dso system command process method to dsoObj.sys
    dsoObj.sys = syscmd.initSysObj.call(dsoObj, 'sys');

    dsoObj.trig = trigcmd.initTrigObj.call(dsoObj, 'trig');

    dsoObj.acq = acqcmd.initAcqObj.call(dsoObj, 'acq');

    dsoObj.hor = horcmd.initHorObj.call(dsoObj, 'hor');

    dsoObj.math = mathcmd.initMathObj.call(dsoObj, 'math');
    dsoObj.meas1 = meascmd.initMeasObj.call(dsoObj, 'meas1');
    dsoObj.meas2 = meascmd.initMeasObj.call(dsoObj, 'meas2');
    dsoObj.meas3 = meascmd.initMeasObj.call(dsoObj, 'meas3');
    dsoObj.meas4 = meascmd.initMeasObj.call(dsoObj, 'meas4');
    dsoObj.meas5 = meascmd.initMeasObj.call(dsoObj, 'meas5');
    dsoObj.meas6 = meascmd.initMeasObj.call(dsoObj, 'meas6');
    dsoObj.meas7 = meascmd.initMeasObj.call(dsoObj, 'meas7');
    dsoObj.meas8 = meascmd.initMeasObj.call(dsoObj, 'meas8');

    dsoObj.ch1 = channel.initChanObj.call(dsoObj, 'ch1');
    dsoObj.ch2 = channel.initChanObj.call(dsoObj, 'ch2');
    dsoObj.ch3 = channel.initChanObj.call(dsoObj, 'ch3');
    dsoObj.ch4 = channel.initChanObj.call(dsoObj, 'ch4');
    // for (var i = 0; i<supportType.length; i++){
    //     log(dsoObj.commandObj[SupportedModel[i]].model[0]);
    // }
    dsoObj.on('cmd_write', dsoObj.cmd_write);
    return dsoObj;
};

/**
*   The class define all needed public properties and methods
*
*   @class dsoctrl
*
*
*/
var _DsoCtrl = function(dsoObj) {
    var dsoctrl = {};

/**
*   The method belong to dsoctrl class used to connect to device,
*   connect method must be called and wait to complete before any dsoctrl method.
*
*   @method connect
*   @param {Function} callback  callback(e) Called when connection has been made
*
*/
    dsoctrl.connect = (function(callback) {
        if (this.interf === 'usb') {
            this.usbConnect(callback);
        }else if (this.interf === 'net') {
            this.tcpConnect(callback);
        }
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to load all properties from device,
*   like trigger type, channel state .. etc.
*
*   @method reloadState
*   @param {Function} callback callback(e) Called when finished loading
*
*/
    dsoctrl.reloadState = (function(callback) {
        var chCmd = [];
        var self = this;
        function reload(e) {
            if (e) {
                if(callback) callback('error');
            }else {
                chCmd[chCmd.length-1].cb = reload;
                if(callback) callback(null);
            }
        };
        // this.reloadState(callback)
        this.cmdSequence = this.cmdSequence.concat(acqLoadCmd);
        this.cmdSequence = this.cmdSequence.concat(trigLoadCmd);
        this.cmdSequence = this.cmdSequence.concat(horLoadCmd);
        for(var i = 0; i < this.maxChNum; i++) {
            chCmd = chanLoadCmd[i].slice(0);
            this.cmdSequence = this.cmdSequence.concat(chCmd);
        }
        chCmd[chCmd.length-1].cb = reload;
        // this.cmdSequence[this.cmdSequence.length-1].cb = reload;
        // log(this.cmdSequence);
        this.emit('cmd_write', this.cmdSequence);

    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to load horizontal properties from device,
*   like time division, position .. etc.
*
*   @method getHorizontal
*   @param {Function} callback callback(e, horProperty) Called when finished loading
*
*/
/**
*   Horizontal property of device.
*
*   @property horProperty
*   @param {String} position Specify the distance with triggered pointer of the main window
*   @param {String} zposition Specify the distance with triggered pointer of the zoom window
*   @param {String} scale Specify the time divison of the main window
*   @param {String} zscale Specify the time divison of the zoom window
*   @param {String} mode Specify which mode device on
*   @param {String} expand Specify timebase expand by center or trigger position
*/
    dsoctrl.getHorizontal = (function(callback) {
        // this.GetSnapshot(callback);
        var self = this;
        function rawData(e) {
            if (e){
                if (callback) callback('error');
            }else {
                if (callback) callback(null, self.hor);
            }
        };
        var cmd = [
                {id:'hor',prop:'HorPosition',arg:'',cb:null,method:'get'},
                {id:'hor',prop:'HorScale',arg:'',cb:null,method:'get'},
                {id:'hor',prop:'HorMode',arg:'',cb:null,method:'get'},
                {id:'hor',prop:'HorExpand',arg:'',cb:null,method:'get'},
                {id:'hor',prop:'HorZoomPosition',arg:'',cb:null,method:'get'},
                {id:'hor',prop:'HorZoomScale',arg:'',cb:rawData,method:'get'}
            ];
        this.cmdSequence = this.cmdSequence.concat(cmd);
        // log(this.cmdSequence);
        this.emit('cmd_write', cmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to load vertical properties from device,
*   like scale, position .. etc.
*
*   @method getVertical
*   @param {String} ch Specify which channel wants to be loaded
*   @param {Function} callback callback(e, chProperty) Called when finished loading
*
*/
/**
*   Channel property of device.
*
*   @property chProperty
*   @param {String} coupling Specify coupling on AC,DC or GND
*   @param {String} impedance Specify the impedance of the analog channel
*   @param {String} invert
*   @param {String} bandwidth
*   @param {String} expand
*   @param {String} state
*   @param {String} position
*   @param {String} deskew
*   @param {String} rawdata
*   @param {String} probe.unit
*   @param {String} probe.atten
*/
    dsoctrl.getVertical = (function(ch, callback) {
        // this.GetSnapshot(callback);
        var self = this;
        var chNum = sytConstant.chID[ch];
        var chCmd;
        function vetical(e) {
            if (e) {
                if (callback) callback('error');
            }else {
                chCmd[chCmd.length-1].cb = null;
                if (callback) callback(null, self[ch]);
            }
        };

        if(chNum < this.maxChNum) {
            chCmd = chanLoadCmd[chNum].slice(0);
            chCmd[chCmd.length-1].cb = vetical;
            this.cmdSequence = this.cmdSequence.concat(chCmd);
            // this.cmdSequence[this.cmdSequence.length-1].cb = vetical;
            // log(chanLoadCmd[chNum]);
            // log('----------------------------');
            this.emit('cmd_write', this.cmdSequence);
        }
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to get the current screen from device,
*
*   @method getSnapshot
*   @param {Function} callback callback(e, dsipData) Called when finished loading
*
*/
    dsoctrl.getSnapshot = (function(callback) {
        // this.GetSnapshot(callback);
        var self = this;
        function snapshot(e) {
            if (e) {
                if (callback) callback('error');
            }else {
                if (callback) callback(null, self.sys.dispData);
            }
        };
        var cmd = [
                {id:'sys',prop:'DispOut',arg:'OFF',cb:snapshot,method:'get'}
            ];
        this.cmdSequence = this.cmdSequence.concat(cmd);
        this.emit('cmd_write', cmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to get the data in acquisition memory for
*   the selected channel form device
*
*   @method getRawdata
*   @param {String} ch Specify which channel wants to be loaded
*   @param {Function} callback callback(e, rawData) Called when finished loading
*
*/
    dsoctrl.getRawdata = (function(ch, callback) {
        // this.GetRawdata(ch,callback);
        var self = this;
        //log(sytConstant.chID[ch]);
        function rawData(e) {
            if (e){
                if (callback) callback('error');

            }else {
                if (callback) callback(null, self[ch].rawdata);
            }

        };

        if(sytConstant.chID[ch] !== undefined){
            var cmd=[
                    {id:'acq',prop:'AcqHeader',arg:'OFF',cb:null,method:'set'},
                    {id:ch,prop:'AcqMemory',arg:'',cb:rawData,method:'get'}
                ];
            this.cmdSequence = this.cmdSequence.concat(cmd);
            this.emit('cmd_write', cmd);

        }else {
            if (callback) callback('error');
        }
        return this;

    }).bind(dsoObj);

    ////////////////////////////
    dsoctrl.onError = (function(callback) {
        this.errHandler = callback;
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to get the edge trigger properties from device
*
*   @method getEdgeTrig
*   @param {Function} callback callback(e, trigProperty) Called when finished loading
*
*/
/**
*   Trigger property of device.
*
*   @property trigProperty
*   @param {String} type
*   @param {String} source
*   @param {String} mode
*   @param {String} holdoff
*   @param {String} noise_rej
*   @param {String} reject
*   @param {String} level
*   @param {String} alt
*   @param {String} state
*   @param {String} edge.coupling
*   @param {String} edge.slop
*/
    dsoctrl.getEdgeTrig = (function(callback) {
        var self = this;
        function edgeTrig(e) {
            if (e) {
                if (callback) callback('error');

            }else {
                if (callback) callback(null, self.trig);
            }

        };
        var trigCmd = [
                {id:'trig',prop:'TrigType',arg:'',cb:null,method:'get'},
                {id:'trig',prop:'TrigSource',arg:'',cb:null,method:'get'},
                {id:'trig',prop:'TrigHighLevel',arg:'',cb:null,method:'get'},
                {id:'trig',prop:'TrigEdgeSlop',arg:'',cb:null,method:'get'},
                {id:'trig',prop:'TrigCouple',arg:'',cb:null,method:'get'},
                {id:'trig',prop:'TrigNoiseRej',arg:'',cb:null,method:'get'},
                {id:'trig',prop:'TrigMode',arg:'',cb:null,method:'get'},
                {id:'trig',prop:'TrigHoldoff',arg:'',cb:edgeTrig,method:'get'}
            ];
        // this.GetRawdata(ch,callback);

        this.cmdSequence = this.cmdSequence.concat(trigCmd);
        this.emit('cmd_write', trigCmd);
    }).bind(dsoObj);


/**
*   The method belong to dsoctrl class used to get the measurment properties
*   for the selected measure channel from device
*
*   @method getMeas
*   @param {String} mCh Specify which measure channel wants to be loaded
*   @param {Function} callback callback(e, measProperty) Called when finished loading
*
*/
/**
*   Measurement property of device.
*
*   @property measProperty
*   @param {String} stdValue
*   @param {String} minValue
*   @param {String} meanValue
*   @param {String} value
*   @param {String} state
*   @param {String} source1
*   @param {String} source2
*   @param {String} type
*   @param {String} state
*/

    dsoctrl.getMeas = (function(mCh, callback) {
        var self = this;
        function measCmd(e) {
            if (e) {
                if(callback) callback('error');

            }else {
                if (callback) callback(null, self[mCh]);
            }
        };
        var measVal = [
                {id:mCh,prop:'MeasureState',arg:'',cb:null,method:'get'},
                // {id:'sys',prop:'StatisticMode',arg:'',cb:null,method:'get'},
                {id:mCh,prop:'MeasureValue',arg:'',cb:null,method:'get'},
                {id:mCh,prop:'MeasureSource1',arg:'',cb:null,method:'get'},
                {id:mCh,prop:'MeasureSource2',arg:'',cb:null,method:'get'},
                {id:mCh,prop:'MeasureType',arg:'',cb:measCmd,method:'get'}
            ];
        var measStd = [
                {id:mCh,prop:'MeasureStd',arg:'',cb:null,method:'get'},
                {id:mCh,prop:'MeasureMin',arg:'',cb:null,method:'get'},
                {id:mCh,prop:'MeasureMean',arg:'',cb:null,method:'get'},
                {id:mCh,prop:'MeasureMax',arg:'',cb:null,method:'get'}
            ];

        if(this.sys.staMode === 'ON'){
            this.cmdSequence = this.cmdSequence.concat(measStd);
        }
        this.cmdSequence = this.cmdSequence.concat(measVal);
        this.emit('cmd_write', measCmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to get the measurment type
*   of device supported
*
*   @method supportedMeasType
*   @param {Array} measureType
*
*/
    dsoctrl.supportedMeasType = (function(callback) {
        var self = this;

        log(this.commandObj[this.gdsType].MeasureType.parameter);
        return this.commandObj[this.gdsType].MeasureType.parameter;
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to setup a periodical measure channel with specify measure type
*   and source channel
*
*   @method setMeas
*   @param {Object} measConf Config to setup a measure channel
*   @param {Function} callback Called when finished setting
*
*/

/**
*
*   Object used to setup a measure channel
*
*   @property measConf
*   @type Object
*   @param {String} src1 Specify first source channel for measurement
*   @param {String} src2 Specify second source channel for delay measure type
*   @param {String} type Specify measure type
*/
    dsoctrl.setMeas = (function(conf,callback) {
        var self = this;
        function measCmd(e){
            if (e) {
                if (callback) {
                    log(e);
                    callback('error');
                }

            }else {
                if (callback) callback();
            }

        };
        var measSet = [
                {id:conf.ch,prop:'MeasureState',arg:'ON',cb:null,method:'set'},
                {id:conf.ch,prop:'MeasureSource1',arg:conf.src1.toUpperCase(),cb:null,method:'set'}
            ],
            measSrc2 = [
                {id:conf.ch,prop:'MeasureSource2',arg:conf.src2.toUpperCase(),cb:null,method:'set'}
            ],
            measType = [
                {id:conf.ch,prop:'MeasureType',arg:conf.type,cb:measCmd,method:'set'}
            ];
        // this.GetRawdata(ch,callback);
        if (conf.type === undefined) {
            meascmd('error');
            return;
        }

        if (conf.src2 !== undefined) {
            this.cmdSequence=this.cmdSequence.concat(measSrc2);
        }

        this.cmdSequence = this.cmdSequence.concat(measSet);
        this.cmdSequence = this.cmdSequence.concat(measType);
        this.emit('cmd_write', measSet);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to turn on statistics for all measure channels
*
*   @method statisticOn
*   @param {Function} callback Called when finished setting
*
*/
    dsoctrl.statisticOn = (function(callback) {
        var self = this;
        function measCmd(e) {
            if (e) {
                if (callback) callback('error');

            }else {
                if (callback) callback(null);
            }
        };
        var measCmd = [
            {id:'sys',prop:'StatisticMode',arg:'ON',cb:measCmd,method:'set'}
        ];

        this.cmdSequence = this.cmdSequence.concat(measCmd);
        this.emit('cmd_write', measCmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to turn off statistics for all measure channels
*
*   @method statisticOff
*   @param {Function} callback Called when finished setting
*
*/
    dsoctrl.statisticOff = (function(callback) {
        var self = this;
        function statistic(e) {
            if (e) {
                if (callback) callback('error');
            }else {
                if (callback) callback(null);
            }

        };
        var sysCmd = [
            {id:'sys',prop:'StatisticMode',arg:'OFF',cb:statistic,method:'set'}
        ];

        this.cmdSequence = this.cmdSequence.concat(sysCmd);
        this.emit('cmd_write', sysCmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to set the statistic weight all measure channels
*
*   @method statisticWeight
*   @param {Number} weight Specify statistic weight
*   @param {Function} callback Called when finished setting
*
*/
    dsoctrl.statisticWeight = (function(weight,callback) {
        var self = this;
        function statistic(e) {
            if (e) {
                if (callback) callback('error');
            }else {
                if (callback) callback(null);
            }

        };
        var sysCmd = [
            {id:'sys',prop:'StatisticStaWeight',arg:weight,cb:statistic,method:'set'}
        ];

        this.cmdSequence = this.cmdSequence.concat(sysCmd);
        this.emit('cmd_write', sysCmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to set the device into run state
*
*   @method run
*   @param {Function} callback Called when finished setting
*
*/
    dsoctrl.run = (function(callback){
        var self = this;
        function sysRun(e){
            if (e) {
                if (callback) callback('error');

            }else {
                if (callback) callback(null);
            }

        };
        var sysCmd = [
            {id:'sys',prop:'RUN',arg:'',cb:sysRun,method:'set'}
        ];

        this.cmdSequence = this.cmdSequence.concat(sysCmd);
        this.emit('cmd_write', sysCmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to set the device into stop state
*
*   @method stop
*   @param {Function} callback Called when finished setting
*/
    dsoctrl.stop = (function(callback) {
        var self = this;
        function sysStop(e) {
            if (e) {
                if (callback) callback('error');

            }else {
                if (callback) callback(null);
            }

        };
        var sysCmd = [
            {id:'sys',prop:'STOP',arg:'',cb:sysStop,method:'set'}
        ];
        log('set dos stop');
        this.cmdSequence = this.cmdSequence.concat(sysCmd);
        this.emit('cmd_write', sysCmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to set the device into single state
*
*   @method single
*   @param {Function} callback Called when finished setting
*/
    dsoctrl.single = (function(callback) {
        var self = this;
        function sysSingle(e) {
            if (e){
                if (callback) callback('error');

            }else {
                if(callback) callback(null);
            }

        };
        var sysCmd = [
            {id:'sys',prop:'SINGLE',arg:'',cb:sysSingle,method:'set'}
        ];

        this.cmdSequence = this.cmdSequence.concat(sysCmd);
        this.emit('cmd_write', sysCmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to set the device into autoset state
*
*   @method Autoset
*   @param {Function} callback Called when finished setting
*/
    dsoctrl.autoset = (function(callback){
        var self = this;
        function sysAutoset(e){
            if (e) {
                if (callback) callback('error');
            }else {
                if (callback) callback(null);
            }

        };
        var sysCmd = [
            {id:'sys',prop:'AUTOSET',arg:'',cb:sysAutoset,method:'set'}
        ];

        this.cmdSequence = this.cmdSequence.concat(sysCmd);
        this.emit('cmd_write', sysCmd);
    }).bind(dsoObj);

/**
*   The method belong to dsoctrl class used to set the device into force trigger state
*
*   @method force
*   @param {Function} callback Called when finished setting
*/
    dsoctrl.force = (function(callback) {
        var self = this;
        function sysForce(e){
            if (e) {
                if (callback) callback('error');

            }else {
                if (callback) callback(null);
            }

        };
        var sysCmd = [
            {id:'sys',prop:'FORCE',arg:'',cb:sysForce,method:'set'}
        ];

        this.cmdSequence = this.cmdSequence.concat(sysCmd);
        this.emit('cmd_write', sysCmd);
    }).bind(dsoObj);


    return dsoctrl;

}

/**
*   Create new instance that used to communicate with instrument through Ethernet
*
*   @class dsoNet
*   @constructor
*   @extends dsoctrl
*   @param {string} port Port number bind to TCP socket
*   @param {string} host_addr Ip address bind to TCP socket
*
*   @return {Object} Return dsoctrl object
*/
exports.DsoNet  = function(port, host_addr) {
    var dsoObj = _DsoObj();
        BindNetObj(dsoObj, port, host_addr);

    return _DsoCtrl(dsoObj);
};

/**
*   Create new instance that used to communicate with instrument through USB
*
*   @class dsoUSB
*   @constructor
*   @extends dsoctrl
*   @param {string} vid Vender ID bind to USB device
*   @param {string} pid Product ID bind to USB device
*
*   @return {Object} Return dsoctrl object
*/
exports.DsoUSB  = function(vid,pid) {

    var dsoObj = _DsoObj();
        usbDev.BindUsbObj(dsoObj, vid, pid);

    return _DsoCtrl(dsoObj);
};