 1Content-type: application/x-Unknown; charset=UTF8package nmc.sidekick;
import javax.comm.SerialPort;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.lang.Exception;

import nmc.common.*;

//(klh)
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Date;

public class MicroKat extends StdInstrumentSensorDriver {

    byte[] _getStatusInfo;
    byte[] _getCalInfo;
    byte[] _getStatusEcho;
    byte[] _getCalEcho;
    byte[] _quitSession;
    byte[] _quitSessionEcho;
    byte[] _haltSample;
    byte[] _haltSampleEcho;
    byte[] _takeSample;
    byte[] _takeSampleEcho;
    byte[] _sendLast;
    byte[] _sendLastEcho;
    byte[] _startNow;
    byte[] _startNowEcho;
    int _maxStatusBytes;
    int _maxCalBytes;
    String _sampleMode;
    
    MicroKat ( ) {

	_name			= "TheMicroKatDriverRev2.1";
   
	_sampleMode		= "TS";
	_enter			= "\r"          .getBytes();
	_prompt			= "S>"          .getBytes();
	_takeSample		= "TS\r"        .getBytes();
	_takeSampleEcho		= "TS\r\n"      .getBytes();
	_sendLast		= "SL\r"        .getBytes();
	_sendLastEcho		= "SL\r\n"      .getBytes();
       
	_sampleRequest	= _takeSample;
	_sampleRequestEcho	= _takeSampleEcho;
	_cfgEol			= "\r\n"        .getBytes();
	_quitSession		= "QS\r"        .getBytes();
	_quitSessionEcho	= "QS"          .getBytes();
	_getStatusInfo		= "DS\r"        .getBytes();
	_getStatusEcho		= "DS\r\n"      .getBytes();
	_getCalInfo		= "DC\r"        .getBytes();
	_getCalEcho		= "DC\r\n"      .getBytes();
	_haltSample		= "STOP\r"      .getBytes();
	_haltSampleEcho	= "STOP"    	.getBytes();
	_startNow		= "STARTNOW\r"  .getBytes();
	_startNowEcho		= "start now"   .getBytes();
	  
	_currentLimit		= 1200; // 11 steps rounded down (120 mA/step) = 1400 mA
	_timeout		= 15000;
	_maxTries		= 3;
	_maxAttnBytes		= 250;
	_maxSampleBytes	= 1000;
	_initMaxTries		= 3;
	_maxSkipBytes		= 512;
	_cfgBufSize		= 512;
	_maxStatusBytes	= 600;
	_maxCalBytes		= 600;
	_callCount                    = 0;
	_powerPolicy                = POWER_NEVER;

    }

public void initialize(){
	// should place into lowest power state based on _powerPolicy 
	// set in ctor
	super.initialize();
	if(_dpaChannel != null){
	   DebugMessage.println("Instrument specific initialization for  "+_name);
	   DebugMessage.println("Setting current limit = "+_currentLimit);
	   _dpaChannel.setCurrentLimit(_currentLimit);
	
	   // this should now be set in super.initialize based on powerPolicy	
	   //DebugMessage.println("Switching Instrument power ON");
	   //_dpaChannel.channelCtrlReg.setInstrumentPowerOn();//set off, do in drvr	
	   //DebugMessage.println("Switching comms power OFF");
	   //_dpaChannel.channelCtrlReg.setCommPowerOff();//set off, turn on in drvr
	   //_dpaChannel.channelCtrlReg.write();
	   	   
	}else{
	   DebugMessage.println("Driver: "+ _name+" initialize(): DPA channel is NULL");	
	}
	DebugMessage.println("Done with initialization");

}// end initialize()


    /** Read a data sample from device communications interface. */
/*
    //public TimestampedData poll() throws Exception {
    public void poll(PollCmd m) throws Exception{
        int tries = 0;
        TimestampedData retVal;
        
       // turn on communications power
       managePowerWake();
       
        while (tries < _maxTries) {
            tries++;
            try {
                byte[] theSample = getMicroKatSample();
                TimestampedData retval = new TimestampedData(theSample);
	        // Now we put the message into an outbound MessageQ, 
	        // instead of returning the TimestampedData.
	        // We may need some Message packetizing here...
                
                PolledDataReply pdr = new PolledDataReply(m,retval);
                _outbound.put(pdr);
              
              // turn off communications power
              managePowerSleep();

                return;

            } catch (TimeoutException e) {
                DebugMessage.println("Driver: '"
                                   + _name
                                   + "' got timeout");
            } // other Exceptions fly past into the caller
        }
        // turn off communications power
       managePowerSleep();
        
       // throw new Exception("Retry limit exceeded (retries=" + tries + ")");
        DebugMessage.println(_name+": Retry limit exceeded (retries=" + tries + ")");
        byte[] retryMsg=(_name+": Retry limit exceeded (retries=" + tries + ")").getBytes();
        TimestampedData retryOut=new TimestampedData(retryMsg);
        PolledDataReply edr = new PolledDataReply(m,retryOut);
        _outbound.put(edr);
    }//end poll()

    private byte[] getMicroKatSample() throws Exception {

      DebugMessage.println("Bypassing actual instrument code...");
      byte[] sampleBuf = new byte[_maxSampleBytes];
      sampleBuf=(new String(("This is some fake uKat data; callCount ="+(_callCount++)))).getBytes();
      int bytesCaptured =sampleBuf.length;
     DebugMessage.println("The data is "+sampleBuf+" len="+bytesCaptured);
      // copy the sample into the exactly-right-sized byte array
      byte[] retval = new byte[bytesCaptured];
      for (int i = 0; i < bytesCaptured; i++) {
          retval[i] = sampleBuf[i];
       }
	
       DebugMessage.println(_name+" Returning...");

       return retval;
    }//end getMicroKatSample()
*/    
    // (klh)
    /** Read instrument configuration from device communications interface. */
    public TimestampedData getConfiguration() throws Exception {
	int tries = 0;
	TimestampedData retVal;
            // Turn on comms power
            commPowerOn();
	// Verify connection...
	DebugMessage.println("getConfiguration: getPrompt...");
	write( _output, _enter );
	skipUntil( _input, _prompt );

        while (tries < _maxTries) {
            tries++;
            try {
                byte[] theSample = getInstrumentConfiguration();
                TimestampedData retval = new TimestampedData(theSample);
                // put instrument back to sleep
		write( _output, _quitSession );
                return retval;
            } catch (TimeoutException e) {
                DebugMessage.println("getInstrumentStatus: ('"
                                   + _name
                                   + "') got timeout");
            } // other Exceptions fly past into the caller
        }
        
        throw new Exception("Retry limit exceeded (retries=" + tries + ")");
    }//end getConfiguration()

    // (klh)
    private byte[] getInstrumentConfiguration() throws Exception {
    	
	// This method should return any available configuration
	// information that is available from the instrument
	// This routine should NOT put the instrument back to
	// sleep, since it is called from other routines whose
	// responsibility it is to do so.

	// Verify connection...
	DebugMessage.println("getInstrumentCfg: getPrompt...");

	write( _output, _enter );
	skipUntil( _input, _prompt );
	
	// Get status/config info...
	DebugMessage.println("Requesting Status Info...");
	write( _output, _getStatusInfo );
	skipUntil(_input,_getStatusEcho);
	byte[] statusBuf = new byte[_maxStatusBytes];
	int statusBytes = readUntil( _input, statusBuf, _prompt );

	// Get cal info...
	DebugMessage.println("Requesting Cal Info...");
	write( _output, _getCalInfo );
	skipUntil(_input,_getCalEcho);
	byte[] calBuf = new byte[_maxCalBytes];
	int calBytes = readUntil( _input, calBuf, _prompt );

	// Get driver config info...
	String drvConfig="";
	drvConfig += "\n_sampleRequest:"+new String(_sampleRequest)+"\n";      	

	// copy the sample into the exactly-right-sized byte array
	byte[] retval = new byte[statusBytes+calBytes+drvConfig.length()];
	for (int i = 0; i < statusBytes; i++) {
	    retval[i] = statusBuf[i];
	}
	for ( int i = 0; i < calBytes; i++) {
	    retval[statusBytes+i] = calBuf[i];
	}
	for ( int i = 0; i < drvConfig.length(); i++) {
	    retval[statusBytes+calBytes+i] = (byte)drvConfig.charAt(i);
	}

	DebugMessage.println(_name+" Returning from getConfiguration()...");
	DebugMessage.println(statusBytes+"+"+calBytes+"+"+drvConfig.length()+"="+retval.length);
      
	return retval;
    }//end getInstrumentConfiguration()

    //public TimestampedData configure(byte[] cfgData) throws Exception {
public void configure(ConfigurationCmd m) throws Exception{
	
        DebugMessage.println("We are in the driver \""
                           + _name
                           + "\" with configuration data="
                           + new String(m.data));

        byte[] tempBuf = new byte[ _cfgBufSize ];

        ByteArrayOutputStream cfgRecord = new ByteArrayOutputStream();

        ByteArrayInputStream cfgSource = new ByteArrayInputStream( m.data );

	// Like the standard instrument driver, the microcat assumes
	// that the byte array sent to it contains lines that containing
	// valid commands that perform some configuration task.
	  
	// For now, the configuration is not verified, but the information
	// will be read back and returned to the caller, offering an
	// incremental improvement over the StdInstrumentDriver, which
	// sends back only its commands.
	  
	// The basic strategy is to send the commands, line by line, to the
	// instrument, recording the both the commands and the resulting
	// responses. After all the lines have been sent, the instrument
	// is polled for its status; the response is combined with the
	// dialog and returned to the caller.
	  
	// Warning: This parsing is pretty fast and loose at this stage.
	// There is no validity checking on the lines sent to the 
	// instrument or their contents.

	// Verify connection...
	flushInput();
	DebugMessage.println("Configure: getPrompt...");
        write( _output, _enter );
        skipUntil( _input, _prompt );
 
	// Halt Sampling...
	DebugMessage.println("Stop sampling...");
        write( _output, _haltSample );
        skipUntil( _input, _haltSampleEcho );
        skipUntil( _input, _prompt );
        
        int count;
        while ( cfgSource.available() > 0 ) {
	    // Get Config Line...
            count = readUntil( cfgSource, tempBuf, _cfgEol );
            String s = new String( tempBuf, 0, count );
            DebugMessage.println("Read config line =" + s);
	    s.trim();

	    int iEqual=s.indexOf('=');
            int iOpenQuote=s.indexOf("\"",0);
            int iCloseQuote=s.lastIndexOf('\"');
	    String param;
	    String value;
		
	    if(iEqual>=1 && iOpenQuote>iEqual && (iCloseQuote>(iOpenQuote+1)) ){
		param = new String(s.substring(0,iEqual).toUpperCase());
		value = new String(s.substring( iOpenQuote+1 , iCloseQuote ));
	    }else{
		param = new String("no param");
		value = new String("no value");
	    }
	    String tmpValue="";
				  
	    // Intercept driver config here...is there a StringTokenizer we could use?

	    // Change sample mode
            if(param.equals("SMODE")){
		tmpValue = value;
		DebugMessage.println("got SMODE: "+ tmpValue+" "+tmpValue.length());
		// Should verify that it is a valid value
		if(tmpValue.equals("SL")){ 
		    _sampleMode="SL";
		    _sampleRequest= _sendLast;
		    _sampleRequestEcho=_sendLastEcho;
		}
		if(tmpValue.equals("TS")){
		    _sampleMode="TS";
		    _sampleRequest=_takeSample;
        	    _sampleRequestEcho=_takeSampleEcho;
		}
			
  	        DebugMessage.println("new _sampleMode = "+ _sampleMode);		      
            }// end SMODE
	    else{
		// Write Config Line to Instrument
		write( _output, tempBuf, count);
		write( _output, _enter );
		DebugMessage.println("wrote config line to _output");

		// Consume instrument response
		count = readUntil( _input, tempBuf, _prompt );
		String s2 = new String(tempBuf, 0, count);
		write( cfgRecord, tempBuf, count + _prompt.length );
		DebugMessage.println("wrote response to config record =" + s2);
	    }
        }

        // Used to resume sampling here, so that it would show up in the status
        // but getInstrumentConfiguration() had trouble getting a prompt afterwards

        // Get instrument status information; this is 
        // what we'll return for now, to verify that our
        // changes have taken place

        byte[] cfgResult = getInstrumentConfiguration();
        
        write( cfgRecord, cfgResult, cfgResult.length);
        DebugMessage.println("wrote config to config record =" + new String(cfgResult));

        byte[] result = cfgRecord.toByteArray();
        cfgRecord.close();
        cfgSource.close();

         // Resume sampling
         if(_sampleMode.equals("SL")){
	flushInput();
	DebugMessage.println("Configure: resuming sampling in SL mode "+new String(_startNow));
    	write( _output, _startNow );
	skipUntil(_input,_startNowEcho);
        }  

        // put instrument back to sleep
        write( _output, _quitSession );
        skipUntil(_input,_quitSessionEcho);
	  
        TimestampedData retval = new TimestampedData( result );

         // Now we put the message into an outbound MessageQ, 
         // instead of returning the TimestampedData.
         // We may need some Message packetizing here...   
         ConfigurationReply cr=new ConfigurationReply(m,retval);
        _outbound.put(cr);
      
         return;

    }// end Configure()
  
}