/*
	Copyright (C) MOXA Inc. All rights reserved.

    This software is distributed under the terms of the
    MOXA License.  See the file COPYING-MOXA for details.
*/

/*
    MxNPortAPI Demo

    A demonstration program uses MxNPortAPI for NPort devices.
*/

package com.moxa.mxnportapidemo;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


import com.moxa.mxnportapi.MxNPort;
import com.moxa.mxnportapi.MxNPortService;
import com.moxa.mxnportapi.MxException;
import com.moxa.mxnportapi.Version;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Scroller;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	private static final String TAG = "mxnportapidemo";

    private boolean mExitThread = false;

	private List<MxNPort> mNPortList = null;
	private MxNPort mCurrentNPort = null;
	private MxNPortService mNPortService;

	private int mPortSelection = -1;
    private int mBaudRate = -1;
    private int mDataBits = -1;
    private int mParity = -1;
    private int mStopBits = -1;
    private int mFlowControl = -1;

    private ArrayAdapter<String> mPortListAdapter;
    private ArrayAdapter<CharSequence> mBaudRateAdapter;
    private ArrayAdapter<CharSequence> mDataBitsAdapter;
    private ArrayAdapter<CharSequence> mParityAdapter;
    private ArrayAdapter<CharSequence> mStopBitsAdapter;
    private ArrayAdapter<CharSequence> mFlowControlAdapter;

    private static EditText mLogText;
    private EditText mWriteEditCtrl;

	private Button mScanButton;
    private Button mOpenButton;
    private Button mCloseButton;
    private Button mWriteButton;
    private Button mPropertyButton;
	private Button mBreakButton;
    private Button mFlushButton;
    private Button mRTSButton;
    private Button mDTRButton;
	private Button mXONButton;
	private Button mXOFFButton;
	private Spinner mNPortSpnner;
    private Spinner mBaudRateSpinner;
    private Spinner mParitySpinner;
    private Spinner mFlowSpinner;
    private Spinner mDataBitsSpinner;
    private Spinner mStopBitsSpinner;

    private Handler handler_result = null;
	private Handler handler_rts = null;
	private Handler handler_dtr = null;

	private int mRtsEnable = MxNPort.RTS_ON;
	private int mDtrEnable = MxNPort.DTR_ON;


    private List<ReadText> mReadTextList = new ArrayList<ReadText>();
    private Object mReadTextLock = new Object();

	class ReadText implements Runnable {

		private String mStr = null;
		private byte[] bufText = null;
		private ByteBuffer mBuf = null;

		ReadText(String s){
			mStr = s;
		}

		ReadText(byte[] buf, int length){
			bufText = Arrays.copyOf(buf, length);
			mBuf = ByteBuffer.wrap( bufText );
		}

		@Override
		public void run() {

			byte ch = 0;

			if( mStr!= null ){
				mLogText.append(mStr);
			}

			if( mBuf!=null ){
				for( int i=0; i<mBuf.limit(); i++ ){
					ch = mBuf.get(i);
					if( (ch<32 || ch>126) && ch!=0x0d && ch!=0x0a ){
						mLogText.append(String.format("[%02X]", ch));
					} else {
						mLogText.append(String.format("%c", ch));
					}
				}
			}
		}

	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		TextView textVersion = (TextView) findViewById(R.id.text_Version);
		textVersion.setText("MxNPortAPI Demo (Library version: " + Version.getString() + ")");

		mLogText = (EditText) findViewById(R.id.text_log);
		mLogText.setScroller(new Scroller(this));
		mLogText.setVerticalScrollBarEnabled(true);
		mLogText.setFocusable(false);
		mLogText.setClickable(false);

		mWriteEditCtrl = (EditText) findViewById(R.id.edit_write);

		mScanButton = (Button) findViewById(R.id.button_scan);
		mOpenButton = (Button) findViewById(R.id.button_open);
		mCloseButton = (Button) findViewById(R.id.button_close);
		mWriteButton = (Button) findViewById(R.id.button_write);
		mPropertyButton = (Button) findViewById(R.id.button_get_property);
		mBreakButton = (Button) findViewById(R.id.button_break);
		mFlushButton = (Button) findViewById(R.id.button_flush);
		mRTSButton = (Button) findViewById(R.id.button_toggle_rts);
		mDTRButton = (Button) findViewById(R.id.button_toggle_dtr);
		mXONButton = (Button) findViewById(R.id.button_xon);
		mXOFFButton = (Button) findViewById(R.id.button_xoff);

		mOpenButton.setEnabled(false);
		mCloseButton.setEnabled(false);
		mWriteButton.setEnabled(false);
		mPropertyButton.setEnabled(false);
		mBreakButton.setEnabled(false);
		mFlushButton.setEnabled(false);
		mRTSButton.setEnabled(false);
		mDTRButton.setEnabled(false);
		mXONButton.setEnabled(false);
		mXOFFButton.setEnabled(false);

        handler_result = new Handler(){
            @Override
            public void handleMessage(Message msg){
                String MsgString = msg.obj.toString();
                mLogText.append(MsgString);
            }

        };

		//
		// Port Name spinner
		//
		mNPortSpnner = (Spinner) findViewById(R.id.spinner_port_name);
		mPortListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, android.R.id.text1);
		mPortListAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		mNPortSpnner.setAdapter(mPortListAdapter);
		mNPortSpnner.setOnItemSelectedListener(
                new OnItemSelectedListener() {
                    public void onItemSelected(
                            AdapterView<?> parent, View view, int position, long id)
                    {
                    	mPortSelection = position;
						mCurrentNPort = mNPortList.get(mPortSelection);
                    }
                    public void onNothingSelected(AdapterView<?> parent) {
                    	mPortSelection = -1;
                    }
                });

        //
		// Baud rate spinner
		//
		mBaudRateSpinner = (Spinner) findViewById(R.id.spinner_baud_rate);

		mBaudRateAdapter = ArrayAdapter.createFromResource(this,
		        R.array.baud_rate_array, android.R.layout.simple_spinner_item);

		mBaudRateAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		mBaudRateSpinner.setAdapter(mBaudRateAdapter);
		mBaudRateSpinner.setSelection(11);

        mBaudRateSpinner.setOnItemSelectedListener(
                new OnItemSelectedListener() {
                    public void onItemSelected(
                            AdapterView<?> parent, View view, int position, long id)
                    {
                    	mBaudRate = Integer.valueOf(mBaudRateAdapter.getItem(position).toString());
                    }
                    public void onNothingSelected(AdapterView<?> parent) {
                    	mBaudRate = -1;
                    }
                });

        //
		// Flow Control spinner
        //
		mFlowSpinner = (Spinner) findViewById(R.id.spinner_flow_control);

		mFlowControlAdapter = ArrayAdapter.createFromResource(this,
		        R.array.flow_control_array, android.R.layout.simple_spinner_item);
		mFlowControlAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		mFlowSpinner.setAdapter(mFlowControlAdapter);
		mFlowSpinner.setSelection(2);

		mFlowSpinner.setOnItemSelectedListener(
                new OnItemSelectedListener() {
                    public void onItemSelected(
                            AdapterView<?> parent, View view, int position, long id)
                    {
                    	mFlowControl = position;
                    }
                    public void onNothingSelected(AdapterView<?> parent) {
                    	mFlowControl = -1;
                    }
                });


        //
		// Data bits spinner
        //
		mDataBitsSpinner = (Spinner) findViewById(R.id.spinner_data_bits);

		mDataBitsAdapter = ArrayAdapter.createFromResource(this,
		        R.array.data_bits_array, android.R.layout.simple_spinner_item);
		mDataBitsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		mDataBitsSpinner.setAdapter(mDataBitsAdapter);
		mDataBitsSpinner.setSelection(3);

		mDataBitsSpinner.setOnItemSelectedListener(
                new OnItemSelectedListener() {
                    public void onItemSelected(
                            AdapterView<?> parent, View view, int position, long id)
                    {
                    	mDataBits = Integer.valueOf(mDataBitsAdapter.getItem(position).toString());
                    }
                    public void onNothingSelected(AdapterView<?> parent) {
                    	mDataBits = -1;
                    }
                });

        //
		// Parity spinner
        //
	    mParitySpinner = (Spinner) findViewById(R.id.spinner_parity);

		mParityAdapter = ArrayAdapter.createFromResource(this,
		        R.array.parity_array, android.R.layout.simple_spinner_item);
		mParityAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		mParitySpinner.setAdapter(mParityAdapter);
		mParitySpinner.setSelection(0);

		mParitySpinner.setOnItemSelectedListener(
                new OnItemSelectedListener() {
                    public void onItemSelected(
                            AdapterView<?> parent, View view, int position, long id)
                    {
                    	mParity = position;
                    }
                    public void onNothingSelected(AdapterView<?> parent) {
                    	mParity = -1;
                    }
                });

		//
		// Stop Bits spinner
        //
	    mStopBitsSpinner = (Spinner) findViewById(R.id.spinner_stop_bits);

		mStopBitsAdapter = ArrayAdapter.createFromResource(this,
		        R.array.stop_bits_array, android.R.layout.simple_spinner_item);
		mStopBitsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		mStopBitsSpinner.setAdapter(mStopBitsAdapter);
		mStopBitsSpinner.setSelection(0);

		mStopBitsSpinner.setOnItemSelectedListener(
                new OnItemSelectedListener() {
                    public void onItemSelected(
                            AdapterView<?> parent, View view, int position, long id)
                    {
                    	mStopBits = Integer.valueOf(mStopBitsAdapter.getItem(position).toString());
                    }
                    public void onNothingSelected(AdapterView<?> parent) {
                    	mDataBits = -1;
                    }
                });


        mWriteEditCtrl.setText("Click write to send!");
		mOpenButton.setFocusableInTouchMode(true);
        mOpenButton.requestFocus();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	public void finish(){
        if( mCurrentNPort!=null ){
            try {
                mCurrentNPort.close();
            } catch (MxException e) {
				e.printStackTrace();
				return;
            }
        }
		super.finish();
	}

	public void OnScan(final View view){

		mPortListAdapter.clear();
		final Handler handler;
		final ProgressDialog progress = ProgressDialog.show(this, "Scaning...", "Wait while scanning");

		handler = new Handler()
		{
			@Override
			public void handleMessage(Message msg){
				Log.d("scan","handler in");
				if (mNPortList != null) {
					mPortListAdapter.clear();
					for (MxNPort p : mNPortList) {
						try {
							mPortListAdapter.add(String.format("Model: %s, IP1: %s, Port Index: %d", p.getNPortModelName(),
									p.getNPortIPAddress(1), p.getNPortPortIndex()));
						} catch (MxException e) {
							e.printStackTrace();
							return;
						}
					}
					mPortListAdapter.notifyDataSetChanged();
				}
				progress.dismiss();

				if(mNPortList.isEmpty()) {
					Toast.makeText(view.getContext(), "Not found device...", Toast.LENGTH_LONG).show();
				}else{
					mOpenButton.setEnabled(true);
				}

			}
		};

		Thread t = new Thread() {
			@Override
			public void run() {
				mNPortList = mNPortService.getNPortInfoList();
				handler.sendEmptyMessage(0);
			}
		};
		t.start();
	}

	private boolean doOpenPort() {
		if( mCurrentNPort!=null ) {
			//
			// Open NPort com port
			//
			try {
				mCurrentNPort.open();
			} catch (MxException e) {
				e.printStackTrace();
                Message msg;
                msg = handler_result.obtainMessage(1, "Failed to open\n");
                handler_result.sendMessage(msg);
				return false;
			}
		}else{
            Message msg;
            msg = handler_result.obtainMessage(1, "Select NPort value is null\n");
            handler_result.sendMessage(msg);
			return false;
		}
		return true;
	}

	private boolean doSetIoctl() {
		MxNPort.IoctlMode mode = new MxNPort.IoctlMode();
		if( mCurrentNPort!=null ) {
			//
			// Get user select baud rate
			//
			mode.baudRate = mBaudRate;

			//
			// Get user select data bits
			//
			switch (mDataBits) {
				case 5:
					mode.dataBits = MxNPort.DATA_BITS_5;
					break;
				case 6:
					mode.dataBits = MxNPort.DATA_BITS_6;
					break;
				case 7:
					mode.dataBits = MxNPort.DATA_BITS_7;
					break;
				case 8:
				default:
					mode.dataBits = MxNPort.DATA_BITS_8;
					break;
			}

			//
			// Get user select parity
			//
			switch (mParity) {
				case 0:
				default:
					mode.parity = MxNPort.PARITY_NONE;
					break;
				case 1:
					mode.parity = MxNPort.PARITY_EVEN;
					break;
				case 2:
					mode.parity = MxNPort.PARITY_ODD;
					break;
			}

			//
			// Get user select stop bits
			//
			switch (mStopBits) {
				case 1:
				default:
					mode.stopBits = MxNPort.STOP_BITS_1;
					break;
				case 2:
					mode.stopBits = MxNPort.STOP_BITS_2;
					break;
			}

			//
			// Set NPort serial com port setting
			//
			try {
				mCurrentNPort.setIoctlMode(mode);
			} catch (MxException e) {
				e.printStackTrace();
                Message msg;
                msg = handler_result.obtainMessage(1, "Failed to set Ioctl\n");
                handler_result.sendMessage(msg);
				return false;
			}
		} else {
            Message msg;
            msg = handler_result.obtainMessage(1, "Select NPort value is null\n");
            handler_result.sendMessage(msg);
			return false;
		}
		return true;
	}

	private boolean doSetFlowCtrl() {
		MxNPort.FlowCtrl flow = new MxNPort.FlowCtrl();

		if( mCurrentNPort!=null ) {
			//
			// Get user select flow control
			//
			switch(mFlowControl){
				case 0:
				default:
					flow.RtsCts = MxNPort.RTSCTS_FLOW_ENABLE;
					break;
				case 1:
					flow.XonXoff = MxNPort.XONXOFF_FLOW_ENABLE;
					break;
				case 2:
					flow.RtsCts &= ~(MxNPort.RTSCTS_FLOW_ENABLE);
					flow.XonXoff &= ~(MxNPort.XONXOFF_FLOW_ENABLE);
					break;
			}

			//
			// Set NPort flow control
			//
			try {
				mCurrentNPort.setFlowCtrl(flow);
			} catch (MxException e) {
				e.printStackTrace();
                Message msg;
                msg = handler_result.obtainMessage(1, "Failed to set flow control\n");
                handler_result.sendMessage(msg);
				return false;
			}
		} else {
            Message msg;
            msg = handler_result.obtainMessage(1, "Select NPort value is null\n");
            handler_result.sendMessage(msg);
			return false;
		}
		return true;
	}

	private boolean doSetRTS(int RTS_status){
		if( mCurrentNPort!=null ) {
			try {
				mCurrentNPort.setRTS(RTS_status);
			} catch (MxException e) {
				e.printStackTrace();
				Message msg;
				msg = handler_result.obtainMessage(1, "Failed to RTS\n");
				handler_result.sendMessage(msg);
				return false;
			}
		} else {
			Message msg;
			msg = handler_result.obtainMessage(1, "Select NPort value is null\n");
			handler_result.sendMessage(msg);
			return false;
		}
		return true;
	}

	private boolean doSetDTR(int DTR_status){
		if( mCurrentNPort!=null ) {
			try {
				mCurrentNPort.setDTR(DTR_status);
			} catch (MxException e) {
				e.printStackTrace();
                Message msg;
                msg = handler_result.obtainMessage(1, "Failed to DTR\n");
                handler_result.sendMessage(msg);
				return false;
			}
		} else {
            Message msg;
            msg = handler_result.obtainMessage(1, "Select NPort value is null\n");
            handler_result.sendMessage(msg);
			return false;
		}
		return true;
	}

	public void OnOpen(final View view){
		mLogText.setText("");
		mLogText.append("OnOpen\n");

		final ProgressDialog progress;
		final Handler handler_open;
		MxNPort.IoctlMode mode = new MxNPort.IoctlMode();
		MxNPort.FlowCtrl flow = new MxNPort.FlowCtrl();

		if( mNPortList ==null ){
			mLogText.append("Device not found\n");
			return;
		}

		progress = ProgressDialog.show(this, "Opening...", "Wait while opening");

		//
		// Get user select NPort serial com port
		//
		mCurrentNPort = mNPortList.get(mPortSelection);

		handler_open = new Handler()
		{
			@Override
			public void handleMessage(Message msg) {

				mExitThread = false;
				Thread threadRead = new Thread()
				{
					@Override
					public void run() {
						//
						//	Thread for reading serial com port data
						//
						int RXBUF_SIZE = 512;
						byte[] dest = new byte[RXBUF_SIZE];
						int length = 0;

						while( mExitThread==false ){
							Arrays.fill(dest, (byte) 0);
							try {
								length = mCurrentNPort.read(dest, RXBUF_SIZE);
							} catch (MxException e){
								Log.e(TAG, "Read data failed.");
								return;
							}
							if( length > 0 ){
								synchronized(mReadTextLock){
									mReadTextList.add(new ReadText(dest, length));
									mReadTextLock.notifyAll();
								}
							} else if( length<0 ) {
								break;
							}
						}
					}
				};
				threadRead.start();

				Thread threadShow = new Thread()
				{
					@Override
					public void run() {
						//
						// thread for updating UI
						//
						while( mExitThread==false ){
							synchronized(mReadTextLock){
								if( !mReadTextList.isEmpty() ){
									runOnUiThread(mReadTextList.remove(0));
								}
								try {
									mReadTextLock.wait(1000);
								} catch (InterruptedException e) {}
							}
						}
					}
				};
				threadShow.start();

				//
				// UI control
				//
				if( mOpenButton.isEnabled() ){
					mBaudRateSpinner.setEnabled(false);
					mParitySpinner.setEnabled(false);
					mFlowSpinner.setEnabled(false);
					mDataBitsSpinner.setEnabled(false);
					mStopBitsSpinner.setEnabled(false);
					mNPortSpnner.setEnabled(false);

					mScanButton.setEnabled(false);
					mOpenButton.setEnabled(false);
					mCloseButton.setEnabled(true);
					mWriteButton.setEnabled(true);
					mPropertyButton.setEnabled(true);
					mBreakButton.setEnabled(true);
					mFlushButton.setEnabled(true);

					MxNPort.FlowCtrl flow = null;
					try {
						flow = mCurrentNPort.getFlowCtrl();
					} catch (MxException e) {
						e.printStackTrace();
						return;
					}

					if(flow.RtsCts != MxNPort.RTSCTS_FLOW_ENABLE)
						mRTSButton.setEnabled(true);

					if(flow.DtrDsr != MxNPort.DTRDSR_FLOW_ENABLE)
						mDTRButton.setEnabled(true);

					if(flow.XonXoff == MxNPort.XONXOFF_FLOW_ENABLE) {
						mXONButton.setEnabled(true);
						mXOFFButton.setEnabled(true);
					}
				}

				mLogText.append("Port opened\n");
				progress.dismiss();
			}
		};

		Thread threadOpen = new Thread()
		{
			@Override
			public void run() {
				boolean ret = false;
				ret = doOpenPort();
				if(!ret){
					progress.dismiss();
					return;
				}
				ret = doSetIoctl();
				if(!ret){
					progress.dismiss();
					return;
				}
				ret = doSetFlowCtrl();
				if(!ret){
					progress.dismiss();
					return;
				}
				ret = doSetRTS(mRtsEnable);
				if(!ret){
					progress.dismiss();
					return;
				}
				ret = doSetDTR(mDtrEnable);
				if(!ret){
					progress.dismiss();
					return;
				}

				handler_open.sendEmptyMessage(0);
			}
		};
		threadOpen.start();
	}

	private void doClosePort(){
		mExitThread = true;

		if (mCurrentNPort != null) {
			//
			// Close NPort serial com port
			//
			Thread threadClose = new Thread() {
				@Override
				public void run() {
					try {
						mCurrentNPort.close();
					} catch (MxException e) {
						e.printStackTrace();
						Message msg = null;
						msg = handler_result.obtainMessage(1, "Failed to close\n");
						handler_result.sendMessage(msg);
						msg = handler_result.obtainMessage(1, "Please retry to close or check NPort setting\n");
						handler_result.sendMessage(msg);
						return;
					}
					mCurrentNPort = null;
				}
			};
			threadClose.start();
			//
			// UI control
			//
			mScanButton.setEnabled(true);
			mCloseButton.setEnabled(false);
			mCloseButton.setEnabled(false);
			mOpenButton.setEnabled(true);
			mWriteButton.setEnabled(false);
			mPropertyButton.setEnabled(false);
			mBreakButton.setEnabled(false);
			mFlushButton.setEnabled(false);
			mRTSButton.setEnabled(false);
			mDTRButton.setEnabled(false);
			mXONButton.setEnabled(false);
			mXOFFButton.setEnabled(false);
			mNPortSpnner.setEnabled(true);
			mBaudRateSpinner.setEnabled(true);
			mParitySpinner.setEnabled(true);
			mFlowSpinner.setEnabled(true);
			mDataBitsSpinner.setEnabled(true);
			mStopBitsSpinner.setEnabled(true);
		} else {
			Message msg = null;
			msg = handler_result.obtainMessage(1, "port is not opened.\n");
			handler_result.sendMessage(msg);
		}
	}

	public void OnClose(View view){
		mLogText.append("OnClose\n");
		doClosePort();
	}

	private void doGetIP(){
		String IP = "";

		//
		// Get NPort IP address
		//
		if(mCurrentNPort != null) {
			try {
				IP = mCurrentNPort.getNPortIPAddress(1) + "";
			} catch (MxException e) {
				e.printStackTrace();
				mLogText.append("Get NPort IP address fail\n");
				return;
			}
			mLogText.append("IP address: " + IP.replace("/", "") + "   ");
			mLogText.append("\n");
		}else{
			mLogText.append("port is not opened.\n");
		}
	}

	private void doGetMac(){
		String MAC = "";

		//
		// Get NPort MAC address
		//
		if(mCurrentNPort != null) {
			char[] hexArray = "0123456789ABCDEF".toCharArray();
			byte[] mac_barray = null;
			try {
				mac_barray = mCurrentNPort.getNPortMACAddress(1);
			} catch (MxException e) {
				e.printStackTrace();
				mLogText.append("Get NPort MAC address fail\n");
				return;
			}

			char[] mac_carray = new char[mac_barray.length * 2];
			for (int i = 0; i < mac_barray.length; i++) {
				int v = mac_barray[i] & 0xff;
				mac_carray[i * 2] = hexArray[v >>> 4];
				mac_carray[i * 2 + 1] = hexArray[v & 0x0f];
			}
			MAC = new String(mac_carray);
			mLogText.append("MAC address: " + MAC + "   ");
			mLogText.append("\n");
		}
	}

	private void doGetOQueue(){
		//
		// Gets the length (in bytes) remaining in the NPort's output buffer
		//
		if(mCurrentNPort != null) {
			Thread threadOQueue = new Thread() {
				@Override
				public void run() {
					int oqueue = 0;
					try {
						oqueue = mCurrentNPort.getOQueue();
					} catch (MxException e) {
						e.printStackTrace();
						Message msg = null;
						msg = handler_result.obtainMessage(1, "Get NPort output buffer fail\n");
						handler_result.sendMessage(msg);
						return;
					}
					Message msg = null;
					msg = handler_result.obtainMessage(1, "OQueue: " + oqueue + "   \n");
					handler_result.sendMessage(msg);
				}
			};
			threadOQueue.start();


		}else{
			mLogText.append("port is not opened.\n");
		}
	}

	private void doGetBaud(){
		int baud = 0;

		//
		// Get NPort current baud rate setting
		//
		if(mCurrentNPort != null) {
			try {
				baud = mCurrentNPort.getBaud();
			} catch (MxException e) {
				e.printStackTrace();
				mLogText.append("Get NPort baud rate fail\n" + e.getMessage() + "\n");
				return;
			}
			mLogText.append("Baud: " + baud + "   ");
		}else{
			mLogText.append("port is not opened.\n");
		}
	}

	private void doGetIoctl(){
		MxNPort.IoctlMode mode = null;

		//
		// Get NPort current serial com port setting
		//
		if(mCurrentNPort != null) {
			try {
				mode = mCurrentNPort.getIoctlMode();
			} catch (MxException e) {
				e.printStackTrace();
				mLogText.append("Get NPort serial com port setting fail\n" + e.getMessage() + "\n");
				return;
			}
			mLogText.append("Data bits: ");
			switch (mode.dataBits) {
				case MxNPort.DATA_BITS_5:
					mLogText.append("5");
					break;
				case MxNPort.DATA_BITS_6:
					mLogText.append("6");
					break;
				case MxNPort.DATA_BITS_7:
					mLogText.append("7");
					break;
				case MxNPort.DATA_BITS_8:
					mLogText.append("8");
					break;
				default:
					mLogText.append("error");
			}
			mLogText.append("   ");

			mLogText.append("Parity: ");
			switch (mode.parity) {
				case MxNPort.PARITY_NONE:
					mLogText.append("None");
					break;
				case MxNPort.PARITY_ODD:
					mLogText.append("Odd");
					break;
				case MxNPort.PARITY_EVEN:
					mLogText.append("Even");
					break;
				default:
					mLogText.append("error");
			}
			mLogText.append("   ");

			mLogText.append("Stop bits: ");
			switch (mode.stopBits) {
				case MxNPort.STOP_BITS_1:
					mLogText.append("1");
					break;
				case MxNPort.STOP_BITS_2:
					mLogText.append("2");
					break;
				case MxNPort.STOP_BITS_1_5:
					mLogText.append("1.5");
					break;
				default:
					mLogText.append("error");
			}
			mLogText.append("\n");
		}else{
			mLogText.append("port is not opened.\n");
		}
	}

	private void doGetFlowCtrl() {
		MxNPort.FlowCtrl flow = null;

		//
		// Get NPort current flow control setting
		//
		if(mCurrentNPort != null) {
			try {
				flow = mCurrentNPort.getFlowCtrl();
			} catch (MxException e) {
				e.printStackTrace();
				mLogText.append("Get NPort flow control setting fail\n" + e.getMessage() + "\n");
				return;
			}
			if ((flow.RtsCts & MxNPort.RTSCTS_FLOW_ENABLE) == MxNPort.RTSCTS_FLOW_ENABLE) {
				mLogText.append("FlowCtrl: RTSCTS enable");
			} else if ((flow.XonXoff & MxNPort.XONXOFF_FLOW_ENABLE) == MxNPort.XONXOFF_FLOW_ENABLE) {
				mLogText.append("FlowCtrl: XONXOFF enable");
			} else {
				mLogText.append("FlowCtrl: None");
			}
			mLogText.append("\n");
		}else{
			mLogText.append("port is not opened.\n");
		}
	}

	private void doGetLineStatus(){
		//
		// Get NPort line status
		//
		if(mCurrentNPort != null) {
			Thread threadLine = new Thread() {
				@Override
				public void run() {
					MxNPort.LineError lineError = null;

					try {
						lineError = mCurrentNPort.getLineStatus();
					} catch (MxException e) {
						e.printStackTrace();
						Message msg;
						msg = handler_result.obtainMessage(1, "Get Line Status Fail.\n" + e.getMessage() + "\n");
						handler_result.sendMessage(msg);
						return;
					}

					if (lineError.parity_error == MxNPort.LINE_ERROR)    //parity error
					{
						Message msg;
						msg = handler_result.obtainMessage(1, "parity_error trigger.\n");
						handler_result.sendMessage(msg);
					}
					if (lineError.framing_error == MxNPort.LINE_ERROR)  //framing error
					{
						Message msg;
						msg = handler_result.obtainMessage(1, "framing_error trigger\n");
						handler_result.sendMessage(msg);
					}
					if (lineError.overrun_error == MxNPort.LINE_ERROR)  //overrun error
					{
						Message msg;
						msg = handler_result.obtainMessage(1, "overrun_error trigger\n");
						handler_result.sendMessage(msg);
					}
				}
			};
			threadLine.start();
		}else{
			mLogText.append("port is not opened.\n");
		}
	}

	public void OnGetProperty(View view){
		if(mCurrentNPort != null){
			mLogText.append("-- Property ---------------------\n");
			doGetOQueue();
			doGetIP();
			doGetMac();
			doGetBaud();
			doGetIoctl();
			doGetFlowCtrl();
			doGetLineStatus();
		}else{
			mLogText.append("port is not opened.\n");
		}
	}



	public void OnFlush(View view){
		if( mCurrentNPort != null ){
			//
			// Flush the NPort output buffer
			//
			Thread threadFlush = new Thread() {
				@Override
				public void run() {
					try {
						mCurrentNPort.flush(MxNPort.FLUSH_OUTPUT);
					} catch (MxException e) {
						Message msg;
						msg = handler_result.obtainMessage(1, "Failed to flush device\n" + e.getMessage() + "\n");
						handler_result.sendMessage(msg);
						return;
					}
					mReadTextList.clear();
					Message msg;
					msg = handler_result.obtainMessage(1, "Port is flush.\n");
					handler_result.sendMessage(msg);
				}
			};
			threadFlush.start();
		}else{
			mLogText.append("port is not opened.\n");
		}
	}

	public void OnToggleDtr(View view){
		Thread threadDtr = new Thread() {
			@Override
			public void run() {
				boolean ret = false;
				if (mCurrentNPort != null) {
					if (mDtrEnable == MxNPort.DTR_ON) {
						mDtrEnable = MxNPort.DTR_OFF;
						Message msg;
						msg = handler_result.obtainMessage(1, "Set DTR OFF");
						handler_result.sendMessage(msg);
					} else {
						mDtrEnable = MxNPort.DTR_ON;
						Message msg;
						msg = handler_result.obtainMessage(1, "Set DTR ON");
						handler_result.sendMessage(msg);
					}
					ret = doSetDTR(mDtrEnable);
					if (!ret) {
						Message msg;
						msg = handler_result.obtainMessage(1, " fail.\n");
						handler_result.sendMessage(msg);
						mDtrEnable = ~mDtrEnable;
					} else {
						Message msg;
						msg = handler_result.obtainMessage(1, " successfully.\n");
						handler_result.sendMessage(msg);
					}
				} else {
					Message msg;
					msg = handler_result.obtainMessage(1, "port is not opened.\n");
					handler_result.sendMessage(msg);
				}
			}
		};
		threadDtr.start();
	}

	public void OnToggleRts(View view){
		Thread threadRtd = new Thread() {
			@Override
			public void run() {
				boolean ret = false;

				if (mCurrentNPort != null) {
					if (mRtsEnable == MxNPort.RTS_ON) {
						mRtsEnable = MxNPort.RTS_OFF;
						Message msg;
						msg = handler_result.obtainMessage(1, "Set RTS OFF");
						handler_result.sendMessage(msg);
					} else {
						mRtsEnable = MxNPort.RTS_ON;
						Message msg;
						msg = handler_result.obtainMessage(1, "Set RTS ON");
						handler_result.sendMessage(msg);
					}
					ret = doSetRTS(mRtsEnable);
					if (!ret) {
						Message msg;
						msg = handler_result.obtainMessage(1, " fail.\n");
						handler_result.sendMessage(msg);
						mRtsEnable = ~mRtsEnable;
					} else {
						Message msg;
						msg = handler_result.obtainMessage(1, " successfully.\n");
						handler_result.sendMessage(msg);
					}
				} else {
					Message msg;
					msg = handler_result.obtainMessage(1, "port is not opened.\n");
					handler_result.sendMessage(msg);
				}
			}
		};
		threadRtd.start();
	}

	public void OnBreak(View view){
		if( mCurrentNPort != null ) {
			//
			// Send break signal to NPort
			//
			Thread threadBreak = new Thread() {
				@Override
				public void run() {
					try {
						mCurrentNPort.setBreak(1000);
					} catch (MxException e) {
						e.printStackTrace();
						Message msg;
						msg = handler_result.obtainMessage(1, "Failed to set break\n" + e.getMessage() + "\n");
						handler_result.sendMessage(msg);
						return;
					}
				}
			};
			threadBreak.start();
		}else{
			mLogText.append("port is not opened.\n");
		}
	}

    private final byte XON           = 0x11;
    public void OnSetXON(View view){
		Thread threadXON = new Thread() {
			@Override
			public void run() {
				byte[] b_xon = new byte[]{XON};
				if (mCurrentNPort != null) {
					//
					// Send XON to NPort
					//
					try {
						mCurrentNPort.write(b_xon);
					} catch (MxException e) {
						e.printStackTrace();
						return;
					}
					Message msg;
					msg = handler_result.obtainMessage(1, "SendXON.\n");
					handler_result.sendMessage(msg);
				} else {
					Message msg;
					msg = handler_result.obtainMessage(1, "port is not opened.\n");
					handler_result.sendMessage(msg);
				}
			}
		};
		threadXON.start();
    }

    private final byte XOFF           = 0x13;
    public void OnSetXOFF(View view){
		Thread threadXOFF = new Thread() {
			@Override
			public void run() {
				byte[] b_xoff = new byte[]{XOFF};

				if (mCurrentNPort != null) {
					//
					// Send XOFF to NPort
					//
					try {
						mCurrentNPort.write(b_xoff);
					} catch (MxException e) {
						e.printStackTrace();
						return;
					}

					Message msg;
					msg = handler_result.obtainMessage(1, "SendXOFF.\n");
					handler_result.sendMessage(msg);
				} else {
					Message msg;
					msg = handler_result.obtainMessage(1, "port is not opened.\n");
					handler_result.sendMessage(msg);
				}
			}
		};
		threadXOFF.start();
    }

	public void OnWrite(View view){
		Thread threadWrite = new Thread() {
			@Override
			public void run() {
				int len = 0;
				byte[] buf = mWriteEditCtrl.getText().toString().getBytes();

				if (mCurrentNPort != null) {
					Message msg;
					msg = handler_result.obtainMessage(1, "OnWrite\n");
					handler_result.sendMessage(msg);
					//
					// Write data to NPort serial COM port
					//
					try {
						len = mCurrentNPort.write(buf);
					} catch (MxException e) {
						e.printStackTrace();
						msg = handler_result.obtainMessage(1, "Failed to write\n" + e.getMessage() + "\n");
						handler_result.sendMessage(msg);
						return;
					}
					msg = handler_result.obtainMessage(1, len+" bytes are written.\n");
					handler_result.sendMessage(msg);
				} else {
					Message msg;
					msg = handler_result.obtainMessage(1, "port is not opened.\n");
					handler_result.sendMessage(msg);
				}
			}
		};
		threadWrite.start();
	}

}
