package com.ai.ced.bluetooth;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Executors;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import cn.com.senter.helper.ShareReferenceSaver;
import cn.com.senter.mediator.BluetoothReader;
import slam.ajni.MyBitmap;
import sunrise.IDImageUtil;
import sunrise.bluetooth.SRBluetoothCardReader;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import com.ai.ced.bluetooth.BtReaderClient.BtStateCallback;
import com.jsunicom.encrylib.EncrylibInterface;
import com.kaer.sdk.IDCardItem;
import com.kaer.sdk.OnClientCallback;
import com.kaer.sdk.bt.BtReadClient;
import com.kaer.sdk.utils.CardCode;
import com.kaeridcard.client.IClientCallBack;
import com.kaeridcard.client.IdCardItem;
import com.sdses.Common;
import com.sdses.Id2Data;
import com.sunnada.SYDReader.IdentityCardZ;
import com.sunnada.bluetooth.SYDBlueReaderHelper;
import com.sunrise.icardreader.helper.ConsantHelper;
import com.sunrise.icardreader.model.IDReadCardInfo;

/**
 * 蓝牙读卡器-安卓cordova插件
 * 支持 卡尔kt8000, kt8003, 森锐, 神思, 恒鸿达
 * @author xmh
 *
 */
public class BluetoothDevicePlugin extends CordovaPlugin implements OnClientCallback{

	//公共变量
	private Activity activity;
	private BluetoothAdapter btAdapter; //android系统自带蓝牙适配器
	private Map<String, BluetoothDevice> devices; //搜索到的所有品牌蓝牙设备全集，key是蓝牙设备的name，value是设备的对象
	private CallbackContext normalCallbackContext; //cordova调用上下文
	private CallbackContext scanDevicesCallbackContext; //搜索设备功能调用上下文，因为会异步多次返回，单独使用
	//private CallbackContext readIDCardCallbackContext; //恒鸿达读身份证调用上下文，因为会异步回调函数，单独使用
	private int nowDeviceType; //当前连接设备类型，主要用来区分当前是不是恒鸿达，用于特别判断
	private String encryptKey; //江苏特供，加密秘钥
	private EncrylibInterface encryptIntface;//江苏特供，加密工具类，神思提供
	private JSONObject config; //保存初始化传进来的配置文件
	private int deviceType_other = 0; //设备类型-未识别的设备
	private int deviceType_kaer_KT8000 = 1; //设备类型-卡尔KT8000
	private int deviceType_senri = 2; //设备类型-森锐
	private int deviceType_sensor = 3; //设备类型-神思
	private int deviceType_hhd = 4; //设备类型-恒鸿达(三元达)
	private int deviceType_kaer_KT8003 = 5; //设备类型-卡尔KT8003
	private int deviceType_senter = 6; // 设备类型-信通

	//卡尔sdk-KT8000
	private com.kaeridcard.client.BtReaderClient kaerClientKt8000; //KT8000的jar包里的
	private IClientCallBack kaerCallback;
	//private boolean is_bt_connect = false;
	//卡尔sdk-KT8003
	private BtReadClient kaerClientKt8003; //KT8003的jar包里的

	//森锐sdk //蓝牙方式接口类
    private SRBluetoothCardReader mBlueReaderHelper;
//    private String senriServerAddress = ""; //IP
//    private int senriServerPort = 0; //端口
    public Handler senriHandler; //回调handler

	//神思sdk
	//private com.sdses.BtReaderClient sensorClient; //神思和卡尔这个类重名，加包名区分
	private BtReaderClient sensorClient; //神思和卡尔这个类重名，卡尔后来从BtReaderClient.jar里拿出来这个类
    private BtStateCallback sensorBtState;

    //恒鸿达sdk
    private SYDBlueReaderHelper mIdUtil;
    public Busi_Idcard_device midHandler;


    // 信通sdk by yd
	private BlueReaderHelper bluecardHelper_xt;
	private HandlerSenter handlerSenter_xt;
	public final static String BLUE_ADDRESSKEY = "CN.COM.SENTER.BLUEADDRESS";
	private String blueaddress = null;




	//总入口
	public boolean execute(String action, JSONArray args,
			CallbackContext callbackContext) throws JSONException {

		JSONObject param = args.getJSONObject(0); // 获取json对象参数
		Log.d("BluetoothDevicePlugin param is", param.toString());

		//初始化各个品牌蓝牙设备的sdk
		if(TextUtils.equals("initBluetoothPlugins", action)) {
			initBluetoothPlugins(param, callbackContext);
			return true;
		}
		//判断手机蓝牙是否开启
		if(TextUtils.equals("checkBluetoothStatus", action)) {
			checkBluetoothStatus(param, callbackContext);
			return true;
		}
		//搜索各个品牌蓝牙设备
		else if (TextUtils.equals("scanDevices", action)){
			scanDevices(param, callbackContext);
			return true;
		}
		//连接蓝牙设备
		else if (TextUtils.equals("connectDevice", action)){
			connectDevice(param, callbackContext);
			return true;
		}
		//读取身份证
		else if (TextUtils.equals("readIDCard", action)){
			readIDCard(param, callbackContext);
			return true;
		}
		//读取sim卡的iccid
		else if (TextUtils.equals("readICCID", action)){
			readICCID(param, callbackContext);
			return true;
		}
		//写sim卡的 imsi和 短信中心
		else if (TextUtils.equals("writeSim", action)){
			writeSim(param, callbackContext);
			return true;
		}
		else{
			Log.d("BluetoothDevicePlugin", "no action found......");

			//返回结果
			JSONObject resp = new JSONObject();
			resp.put("respCode", "9999");
			resp.put("respDesc", "不存在此操作");
			sendRespInfo(resp, callbackContext);
			return true;
		}

	}

	/**
	 * 初始化各品牌蓝牙设备
	 * param 入参例子如下湖北的：
	 * {'kt8000':{},
	 *  'kt8003':{'ip':'115.28.2.173', 'port':'7443', 'acct':'admin', 'password':'www.kaer.cn'},
	 *  'senri':{'ip':'113.57.239.241', 'port':'6000', 'acct':'uni_hb_wsl', 'password':'dg8@#LfL', 'key':'FE870B0163113409C134283661490AEF'},
	 *  'sensor':{},
	 *  'hhd':{'ip':'hodiddec.com', 'port':'18000', 'imageDecUrl':'http://hodpicdec.com:18080/Inter-Real/photoDecode'}
    }
	 * @param param
	 * @param callbackContext
	 * @throws JSONException
	 */
	private void initBluetoothPlugins(JSONObject param, CallbackContext callbackContext) throws JSONException{
		Log.d("BluetoothDevicePlugin", "initBluetoothPlugins......");
		//设置cordova调用上下文
		this.normalCallbackContext = callbackContext;
		//保存初始化传进来的配置文件，后面如果断连需要重新初始化时会用到
		this.config = param;

		//param 就是每个省的配置参数，里面有各个品牌型号的需要的初始化信息
		JSONObject kt8000 = param.getJSONObject("kt8000");
		JSONObject kt8003 = param.getJSONObject("kt8003");
		JSONObject senri = param.getJSONObject("senri");
		JSONObject sensor = param.getJSONObject("sensor");
		JSONObject hhd = param.getJSONObject("hhd");
		JSONObject senter = param.getJSONObject("senter");

		//返回结果
		JSONObject resp = new JSONObject();

		//初始化安卓蓝牙和devices
		int i = initCommon();
		//手机支持蓝牙才继续执行下面的初始化
		if(i == 0){
			//卡尔初始化 KT8000
			initKaerDeviceKT8000(kt8000);
			//森锐初始化
			initSenriDevice(senri);
			//神思初始化
			initSensorDevice(sensor);
			//恒鸿达初始化
			initHhdDevice(hhd);
			//卡尔初始化 KT8003
			initKaerDeviceKT8003(kt8003);
			//信通初始化
			initSenterDevice(senter);

			resp.put("respCode", "0000");
			resp.put("respDesc", "蓝牙读卡器初始化成功");
		}
		else if (i == 1){
			resp.put("respCode", "0001");
			resp.put("respDesc", "您的手机不支持蓝牙");
		}
		else if (i == 2){
			//这边不会有这个返回，因为initCommon()里我会强制打开蓝牙
			resp.put("respCode", "0002");
			resp.put("respDesc", "手机蓝牙未打开");
		}
		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);

	}

	/**
	 * 初始化设备-公共变量
	 * 返回0：成功 , 1:手机不支持蓝牙 2：手机蓝牙没打开
	 * @return
	 */
	private int initCommon(){
		Log.d("BluetoothDevicePlugin", "initCommon......");

		//
		activity = cordova.getActivity();

		//加密类初始化，江苏特供，神思提供
		encryptIntface = new EncrylibInterface();

		//初始化设备集合
		devices = new HashMap<String, BluetoothDevice>();
		//初始化安卓系统蓝牙适配器
		btAdapter = BluetoothAdapter.getDefaultAdapter();
		if (btAdapter == null) {
           return 1; //手机不支持蓝牙
		}
		if (btAdapter.getState() != BluetoothAdapter.STATE_ON){
		   //return 2; //手机蓝牙没打开
			Log.d("BluetoothDevicePlugin", "initCommon......蓝牙没开强制打开");
			//如果没开就 强制打开蓝牙
		   boolean b = btAdapter.enable();
			// 注册Receiver来获取蓝牙设备相关的结果
			IntentFilter intent = new IntentFilter();
			intent.addAction(BluetoothDevice.ACTION_FOUND);
			intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
			intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
			activity.registerReceiver(searchDevices, intent);
		   return 0; //这边
		}

		// 注册Receiver来获取蓝牙设备相关的结果
		IntentFilter intent = new IntentFilter();
		intent.addAction(BluetoothDevice.ACTION_FOUND);
		intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
		intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		activity.registerReceiver(searchDevices, intent);

		return 0;
	}

	/**
	 * 用BroadcastReceiver来取得搜索结果
	 */
	private BroadcastReceiver searchDevices = new BroadcastReceiver() {

		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			//搜索到蓝牙设备
			if (action.equals(BluetoothDevice.ACTION_FOUND)) {
				BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				String device_name = device.getName();//蓝牙设备名称
				Log.d("BluetoothDevicePlugin", "searchDevices found......" + device_name);
				int device_type = deviceTypeFromName(device_name);//根据名称获取设备品牌类型
				//搜到的蓝牙设备里发现会有些name是空的,舍弃
				//搜到的蓝牙设备如果不是卡尔，森锐，神思的，舍弃
				if(device_type == 0){
					Log.d("BluetoothDevicePlugin", "searchDevices found is not KT8000 SR SS HHD KT8003......out");
					return;
				}

				//String device_mac = device.getAddress();//mac地址
				//搜到的设备添加到 devices里面，防止重复添加，而且只添加KT,SR,SS开头的
				if(!devices.containsKey(device_name)){
					devices.put(device_name, device);
				}

				//返回结果
				JSONObject resp = new JSONObject();
				try {
					resp.put("respCode", "0000");
					resp.put("respDesc", "搜索到蓝牙读卡器设备......");
					JSONArray data = new JSONArray();
					//只返回设备的name的array
					Iterator iter = devices.entrySet().iterator();
					while (iter.hasNext()) {
						Map.Entry entry = (Map.Entry) iter.next();
						data.put(entry.getKey());
					}
					resp.put("data", data);
				} catch (JSONException e) {
					e.printStackTrace();
				}
				//返回结果
				sendRespInfo(resp, scanDevicesCallbackContext);

			}
			//开始扫描周围设备
			else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
				Log.d("BluetoothDevicePlugin", "searchDevices start......");
			}
			//扫描周围设备完成
			else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
				Log.d("BluetoothDevicePlugin", "searchDevices finish......");
			}
		}
	};

	/**
	 * 初始化设备-卡尔-KT8000
	 */
	private void initKaerDeviceKT8000(JSONObject param){
		Log.d("BluetoothDevicePlugin", "initKaerDevice......");

		kaerClientKt8000 = new com.kaeridcard.client.BtReaderClient(activity); //KT8000的构造函数
		//这个sdk要求必须实现，只是这边不需要任何逻辑
		kaerCallback = new IClientCallBack() {
			@Override
			public void onBtState(final boolean is_connect) {
				Log.d("BluetoothDevicePlugin", "IClientCallBack onBtState......" + is_connect);
			}

			@Override
			public void onIddataHandle(IdCardItem iddata) {

			}
		};
		kaerClientKt8000.setCallBack(kaerCallback);

        Log.d("BluetoothDevicePlugin", "initKaerDevice......success");
	}

	/**
	 * 初始化设备-卡尔-KT8003
	 * @throws JSONException
	 */
	private int initKaerDeviceKT8003(JSONObject param) throws JSONException{
		Log.d("BluetoothDevicePlugin", "initKaerDeviceKT8003......");

		//获取配置参数
		String ip = param.getString("ip");
		String port = param.getString("port");
		String acct = param.getString("acct");
		String password = param.getString("password");

		kaerClientKt8003 = BtReadClient.getInstance(); //KT8003的构造函数
		kaerClientKt8003.setClientCallback(this);
		//ip, port, 账号，密码，是否wss连接，默认true，这边写的是测试服务器，取自demo
//		String ip = "115.28.2.173";
//		int port = 7443;
//		String acct = "admin";
//		String password = "www.kaer.cn";
        int result = kaerClientKt8003.init(activity, ip, Integer.parseInt(port), acct, getMD5(password.getBytes()), true);
        kaerMsgHandler.obtainMessage(900, result, result).sendToTarget();

        if(result == 0){
        	Log.d("BluetoothDevicePlugin", "initKaerDeviceKT8003......success");
        }
        else{
        	Log.d("BluetoothDevicePlugin", "initKaerDeviceKT8003......error," + result);
        }

        return result;
	}

	/**
	 * 初始化设备-森锐
	 * @throws JSONException
	 */
	private void initSenriDevice(JSONObject param) throws JSONException {
		Log.d("BluetoothDevicePlugin", "initSenriDevice......");

		//new一个自定义handler消息处理类
		senriHandler = new SenriHandler();

		String ip = param.getString("ip");
		String port = param.getString("port");
		String acct = param.getString("acct");
		String password = param.getString("password");
		String key = param.getString("key");

		// 初始化阅读器, 账号、密码、密钥
		mBlueReaderHelper = new SRBluetoothCardReader(senriHandler, activity,
				acct, password, key);

        // 设置特定的解密服务器
		//initShareReference();
        //先把管控设为空
        mBlueReaderHelper.enableAutoServer(false);
        //设入特定的服务器
        mBlueReaderHelper.setTheServer(ip, Integer.parseInt(port));

        //解密服务监听器，可监听连接的是哪台解密服务器
//        mBlueReaderHelper.setDecodeServerListener(new IDecodeIDServerListener() {
//            @Override
//            public void getThisServer(String ip, int port) {
//            	senriHandler.obtainMessage(SERVER_TV, ip + "-" + port).sendToTarget();
//            }
//        });

		Log.d("BluetoothDevicePlugin", "initSenriDevice......success");
	}

	/**
	 * 初始化设备-神思
	 */
	private void initSensorDevice(JSONObject param){
		Log.d("BluetoothDevicePlugin", "initSensorDevice......");
		//sensorClient = new com.sdses.BtReaderClient(activity);
		sensorClient = new BtReaderClient(activity);
		//mBtState = new ReceiveBtStateData();
		sensorBtState = new BtStateCallback(){
			@Override
			public void onBtState(int arg0, int arg1, Activity arg2) {
				//返回结果
				JSONObject resp = new JSONObject();

				if(arg0 == Common.MESSAGE_CONNECT_SUCCEED){
					Log.d("BluetoothDevicePlugin", "sensor BtStateCallback onBtState......connect succed");
					//tvLog.setText("蓝牙连接成功\n");

					try {
						resp.put("respCode", "0000");
						resp.put("respDesc", "神思蓝牙读卡器连接成功");
					} catch (JSONException e) {
						e.printStackTrace();
					}
				}else if(arg0 == Common.MESSAGE_CONNECT_LOST){
					Log.d("BluetoothDevicePlugin", "sensor BtStateCallback onBtState......connect lost");
					//tvLog.setText("蓝牙连接失败\n");

					try {
						resp.put("respCode", "0003");
						resp.put("respDesc", "神思蓝牙读卡器连接失败");
					} catch (JSONException e) {
						e.printStackTrace();
					}
				}

//				//因为恒鸿达每次读卡写卡等都需要先连接，操作完又会自动断开，所以每次操作都会返回3次，这边恒鸿达特殊判断，不返回
//				if(nowDeviceType == deviceType_hhd){
//					return;
//				}

				//其他牌子的蓝牙连接成功也会触发这个回调，所以这边判断下，只有神思的才在这边返回
				//卡尔的会在自己的连接函数后同步返回，
				//森锐的每次操作都要重新连接，会有个假的连接成功返回，
				//三元达的每次操作都需要重新连接，会有个假的连接成功返回，
				if(nowDeviceType != deviceType_sensor){
					return;
				}

				//返回结果
				sendRespInfo(resp, normalCallbackContext);

			}
		};
		sensorClient.setCallBack(sensorBtState);
		sensorClient.Start();

		Log.d("BluetoothDevicePlugin", "initSensorDevice......success");
	}

	/**
	 * 初始化设备-恒鸿达
	 * @throws JSONException
	 *
	 */
	private void initHhdDevice(JSONObject param) throws JSONException {
		Log.d("BluetoothDevicePlugin", "initHhdDevice......");

		//获取配置参数
		String ip = param.getString("ip"); //传的其实是域名 "hodiddec.com"
		String port = param.getString("port");
//		String acct = param.getString("acct");
//		String password = param.getString("password");

		//打印手机的imei，恒鸿达的设备会校验imei，测试发现老手机没问题，mate9cordova兼容有问题，读取imei=0000000，导致读不了
//        TelephonyManager 	mPhoneManager;
//		mPhoneManager = (TelephonyManager)activity.getSystemService(Context.TELEPHONY_SERVICE);
//		String StrTmp =  mPhoneManager.getDeviceId() ;
//		Log.d("BluetoothDevicePlugin", "imei......" + StrTmp);

		midHandler = new Busi_Idcard_device(activity);
		mIdUtil = new SYDBlueReaderHelper(midHandler.mHandler, activity);

//		mIdUtil.close();//清除之前的连接
		//设置服务器ip和port
		mIdUtil.setTheServer(GetInetAddress(ip), Integer.valueOf(port), GetInetAddress(ip), Integer.valueOf(port));
        //注册读身份证后的回调函数
		registerHhdReadIDCardCallback();

		com.sunnada.SYDReader.k.b = true; //打印恒鸿达sdk日志开关

		Log.d("BluetoothDevicePlugin", "initHhdDevice......success");
	}

	/**
	 * 初始化设备-信通
	 */
	private void initSenterDevice(JSONObject param) throws JSONException {
		Log.d("BluetoothDevicePlugin", "initSenterDevice......");
		//获取配置参数
		String ip = param.getString("ip"); //传的其实是域名 "senter-online.cn"
		String port = param.getString("port"); // 10002

		Log.d("BluetoothDevicePlugin", "initSenterDevice......ip" + ip);
		Log.d("BluetoothDevicePlugin", "initSenterDevice......port" + port);

        // 初始化handler
        handlerSenter_xt = new HandlerSenter(activity, this.normalCallbackContext);

		// 初始化bluecardHelper
		bluecardHelper_xt = new BlueReaderHelper(activity, handlerSenter_xt);

		// 设置ip和端口
		bluecardHelper_xt.setServerAddress(ip);
		bluecardHelper_xt.setServerPort(Integer.parseInt(port));

	}



	/**
	 * 恒鸿达-注册读身份证后的回调函数
	 * readCard()后回调
	 */
	private void registerHhdReadIDCardCallback() {
		midHandler.setIdCardCallback(new CallBack() {
			public void HandleResult(IdentityCardZ idCardArray, byte[] image,
					short[] imagelen) {
				Log.d("BluetoothDevicePlugin", "readIDCardHhd......HandleResult");
				// 返回结果
				JSONObject resp = new JSONObject();

				try {
					if (idCardArray != null) {
						resp.put("respCode", "0000");
						resp.put("respDesc", "读取身份证成功");

						JSONObject data = new JSONObject();
						data.put("name", idCardArray.name); // 姓名
						data.put("sexCode", idCardArray.sex.equals("男") ? "1" : "0");// 性别
						data.put("sexName", idCardArray.sex);// 性别
						data.put("birth", idCardArray.birth);// 生日yyyymmdd
						data.put("nationCode", "");// 民族编码, 恒鸿达没有
						data.put("nationName", idCardArray.ethnicity);// 民族汉字
						data.put("address", idCardArray.address);// 住址
						data.put("idNum", idCardArray.cardNo);// 身份证号
						data.put("signOffice", idCardArray.authority);// 发证机关
						// 有些身份证是永久有效的可能没有结束日期
						String[] usefuldates = idCardArray.period.split("-");
						String usefulStartDate = usefuldates[0];
						String usefulEndDate = usefuldates[1];
						if (usefulEndDate == null || usefulEndDate.equals("")) {
							usefulEndDate = "20991231";
						}
						data.put("usefulStartDate", usefulStartDate);// 有效期开始yyyymmdd
						data.put("usefulEndDate", usefulEndDate);// 有效期结束yyyymmdd

						// 处理图片
						if (idCardArray.avatar != null) {
							// 解码头像
							int res = -1;
							byte[] szImageData = new byte[306 * 126];
							try {
								res = com.guoguang.jni.JniCall.Huaxu_Wlt2Bmp(
										idCardArray.avatar, szImageData, 708);

								if (res != 1) {
									szImageData = null;
								}
							} catch (Exception e) {
								szImageData = null;
								e.printStackTrace();
							}

							if (szImageData != null) {
								Bitmap bitmap = MyBitmap.createMyBitmap(
										szImageData, 102, 126);
								String picStr = bitmapToBase64(bitmap); // 照片base64字符串
								data.put("pic", picStr);
							} else {
								data.put("pic", "");
							}

						} else {
							data.put("pic", "");
						}

						//江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
						if(!TextUtils.isEmpty(encryptKey)){
							Log.d("BluetoothDevicePlugin", "encryptKey is ......" + encryptKey);
			                String nameEncript = encryptIntface.Id2DataEncry(encryptKey, idCardArray.name);
			                String idNumEncript = encryptIntface.Id2DataEncry(encryptKey, idCardArray.cardNo);
			                String addressEncript = encryptIntface.Id2DataEncry(encryptKey, idCardArray.address);

			                data.put("nameEncript", nameEncript);//姓名加密后
			                data.put("idNumEncript", idNumEncript);//身份证号加密后
			                data.put("addressEncript", addressEncript);//住址加密后
						}

						resp.put("data", data);
					} else {
						resp.put("respCode", "0005");
						resp.put("respDesc", "恒鸿达读取身份证错误");
					}
				} catch (JSONException e1) {
					Log.d("BluetoothDevicePlugin", "readIDCardHhd......HandleResult......exception");
					try {
						resp.put("respCode", "0005");
						resp.put("respDesc", "恒鸿达读取身份证异常");
					} catch (JSONException e) {
						e.printStackTrace();
					}

					e1.printStackTrace();
				}

				// 返回结果
				sendRespInfo(resp, normalCallbackContext);
			}

		});
	}




	/**
	 * 判断手机蓝牙是否开启
	 * @param param
	 * @param callbackContext
	 * @throws JSONException
	 */
	private void checkBluetoothStatus(JSONObject param, CallbackContext callbackContext) throws JSONException{
		Log.d("BluetoothDevicePlugin", "checkBluetoothStatus......");
		//设置cordova调用上下文
		this.normalCallbackContext = callbackContext;
		//返回结果
		JSONObject resp = new JSONObject();

		//初始化安卓蓝牙和devices
		int i = initCommon();
		//手机支持蓝牙才继续执行下面的初始化
		if(btAdapter.isEnabled()){
			resp.put("respCode", "0000");
			resp.put("respDesc", "手机蓝牙已开启");
		}
		else {
			resp.put("respCode", "0020");
			resp.put("respDesc", "手机蓝牙未开启");
		}
		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);

	}

	/**
	 * 搜索蓝牙设备
	 * 会在回调函数 searchDevices 里多次返回结果集
	 * @param param
	 * @param callbackContext
	 * @throws JSONException
	 */
	private void scanDevices(JSONObject param, CallbackContext callbackContext) throws JSONException{
		Log.d("BluetoothDevicePlugin", "scanDevices......");
		//设置cordova调用上下文
		this.scanDevicesCallbackContext = callbackContext;
		//返回结果
		JSONObject resp = new JSONObject();

		//手机蓝牙开启时才执行搜索
		if (btAdapter.getState() == BluetoothAdapter.STATE_ON){
			//如果正在搜索，则先停止搜索，清空列表，再搜索
			if (btAdapter.isDiscovering()) {
				btAdapter.cancelDiscovery(); //先停止搜索
				//devices.clear(); //搜索前清空设备列表
				btAdapter.startDiscovery(); //开始搜索
			}
			else{
				//devices.clear(); //搜索前清空设备列表
				btAdapter.startDiscovery(); //开始搜索
			}

			//开始返回结果，开始搜索时返回一次，后面searchDevices搜到每一个设备都会返回一次全量结果集
//			resp.put("respCode", "0000");
//			resp.put("respDesc", "蓝牙读卡器搜索中......");
//			List<String> data = new ArrayList<String>();
//			data.addAll(devices.keySet()); //只返回名字的列表，此时应该是空list
//			resp.put("data", data);
		}
		else {
			resp.put("respCode", "0002");
			resp.put("respDesc", "手机蓝牙未打开");
			//返回结果
			sendRespInfo(resp, this.scanDevicesCallbackContext);
		}
	}

	/**
	 * 连接蓝牙设备
	 * @param param
	 * @param callbackContext
	 * @throws JSONException
	 */
	private void connectDevice(JSONObject param, CallbackContext callbackContext) throws JSONException{
		Log.d("BluetoothDevicePlugin", "connectDevice......");
		//设置cordova调用上下文
		this.normalCallbackContext = callbackContext;

		//返回结果
		JSONObject resp = new JSONObject();

		String name = param.getString("name"); //获取蓝牙设备的名字
		int deviceType = deviceTypeFromName(name); //根据名字获取设备类型
		this.nowDeviceType = deviceType; //当前连接设备类型
		Log.d("BluetoothDevicePlugin", "connectDevice......deviceType：" + deviceType);

		Iterator iter = devices.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			Object key = entry.getKey();
			Log.d("BluetoothDevicePlugin", "devices has key name：" + key);
		}

		//手机蓝牙开启时才执行搜索
		if (btAdapter.getState() == BluetoothAdapter.STATE_ON){
			if (deviceType == deviceType_kaer_KT8000) {
				BluetoothDevice deviceInfo = devices.get(name);
				boolean result = connectDeviceKaerKT8000(deviceInfo); //卡尔-KT8000

				//开始返回结果
				if(result){
					resp.put("respCode", "0000");
					resp.put("respDesc", "卡尔蓝牙读卡器连接成功");
				}
				else{
					resp.put("respCode", "0003");
					resp.put("respDesc", "卡尔蓝牙读卡器连接失败");
				}
				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
			}
			else if (deviceType == deviceType_kaer_KT8003) {
				BluetoothDevice deviceInfo = devices.get(name);
				boolean result = connectDeviceKaerKT8003(deviceInfo); //卡尔-KT8003

				//开始返回结果
				if(result){
					resp.put("respCode", "0000");
					resp.put("respDesc", "卡尔蓝牙读卡器连接成功");
				}
				else{
					resp.put("respCode", "0003");
					resp.put("respDesc", "卡尔蓝牙读卡器连接失败");
				}
				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
			}
			else if (deviceType == deviceType_senri) {
				BluetoothDevice deviceInfo = devices.get(name);
				connectDeviceSenri(deviceInfo); //其实里面啥操作也没有
				//开始返回结果
				resp.put("respCode", "0000");
				resp.put("respDesc", "森锐蓝牙读卡器连接成功");
				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
			}
			else if (deviceType == deviceType_sensor) {
				BluetoothDevice deviceInfo = devices.get(name);
				connectDeviceSensor(deviceInfo); //神思连接设备后，通过回调函数BtStateCallback返回结果
			}
			else if (deviceType == deviceType_hhd) {
				BluetoothDevice deviceInfo = devices.get(name);
				connectDeviceHhd(deviceInfo); //其实里面啥操作也没有

				//直接返回连接成功
				resp.put("respCode", "0000");
				resp.put("respDesc", "恒鸿达蓝牙读卡器连接成功");
				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
			}else if (deviceType == deviceType_senter) {
				BluetoothDevice deviceInfo = devices.get(name);
				connectDeviceSenter(deviceInfo); //其实里面啥操作也没有
				//直接返回连接成功
				resp.put("respCode", "0000");
				resp.put("respDesc", "信通蓝牙读卡器连接成功");
				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
			}
			else{
				resp.put("respCode", "9998");
				resp.put("respDesc", "该蓝牙读卡器名字未匹配到对应品牌");
				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
			}


		}
		else {
			resp.put("respCode", "0002");
			resp.put("respDesc", "手机蓝牙未打开");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
		}


	}

	/**
	 * 卡尔-连接蓝牙设备-KT8000
	 * @param deviceInfo
	 * @return
	 */
	private boolean connectDeviceKaerKT8000(BluetoothDevice deviceInfo) {
		Log.d("BluetoothDevicePlugin", "connectDeviceKaer......");
		String mac = deviceInfo.getAddress();
		//kaerClient.disconnectBt();
		return kaerClientKt8000.connectBt(mac);
	}

	/**
	 * 卡尔-连接蓝牙设备-KT8003
	 * @param deviceInfo
	 * @return
	 */
	private boolean connectDeviceKaerKT8003(BluetoothDevice deviceInfo) {
		Log.d("BluetoothDevicePlugin", "connectDeviceKaerKT8003......");
		String mac = deviceInfo.getAddress();
		//kaerClient.disconnectBt();
		return kaerClientKt8003.connectBt(mac);
	}

	/**
	 * 森锐-连接蓝牙设备
	 * 森锐每次读身份证等操作都需要重新连接，所以这边什么也不需要做
	 * @param deviceInfo
	 * @return
	 */
	private void connectDeviceSenri(BluetoothDevice deviceInfo) {
		Log.d("BluetoothDevicePlugin", "connectDeviceSenri......");
		String name = deviceInfo.getName();
		String mac = deviceInfo.getAddress();

//        //连接设备
//        boolean isRegisterBT = mBlueReaderHelper.registerBlueCard(mac);
//        //senriHandler.sendEmptyMessage(REGISTER_BLUETOOTH);
//        return isRegisterBT;
	}

	/**
	 * 神思-连接蓝牙设备
	 * 神思不是同步返回连接状态结果的，是通过回调函数BtStateCallback返回的
	 * @param deviceInfo
	 * @return
	 */
	private void connectDeviceSensor(BluetoothDevice deviceInfo) {
		Log.d("BluetoothDevicePlugin", "connectDeviceSensor......");
		String name = deviceInfo.getName();
		String mac = deviceInfo.getAddress();
		//sensorClient.disconnect(); //不加这句，神思的每次只能读一次，第二次就读不了
		sensorClient.connectBt(mac, name);
	}

	/**
	 * 恒鸿达-连接蓝牙设备
	 * 恒鸿达设备每次操作完都会自动断开连接，所以这边连接就没有用了，什么也不做
	 * @param deviceInfo
	 * @return
	 */
	private void connectDeviceHhd(BluetoothDevice deviceInfo) {
		Log.d("BluetoothDevicePlugin", "connectDeviceHhd......");
		String name = deviceInfo.getName();
		String mac = deviceInfo.getAddress();

		//return mIdUtil.registerBlueCard(mac);
	}

	/**
	 * 信通-连接蓝牙设备
	 * @param deviceInfo
	 * @return
	 */
	private void connectDeviceSenter(BluetoothDevice deviceInfo) {
		Log.d("BluetoothDevicePlugin", "connectDeviceXT......");
		String name = deviceInfo.getName();
		String mac = deviceInfo.getAddress();
		Log.d("BluetoothDevicePlugin", "connectDeviceXT......name" + name);
		Log.d("BluetoothDevicePlugin", "connectDeviceXT......mac" + mac);

		blueaddress = mac;

//		bluecardHelper_xt.registerBlueCard(mac);

		//return mIdUtil.registerBlueCard(mac);
	}



	/**
	 * 读身份证
	 * @param param
	 * @param callbackContext
	 * @throws JSONException
	 */
	private void readIDCard(JSONObject param, CallbackContext callbackContext) throws JSONException{
		Log.d("BluetoothDevicePlugin", "readIDCard......");

		//设置cordova调用上下文
		this.normalCallbackContext = callbackContext;
		//this.readIDCardCallbackContext = callbackContext; //恒鸿达的读身份证是回调函数返回的

		String name = param.getString("name"); //获取蓝牙设备的名字
		this.encryptKey = param.getString("encryptKey"); //加密秘钥，江苏特供，其他省可以不传或者传""
		int deviceType = deviceTypeFromName(name); //根据名字获取设备类型
		Log.d("BluetoothDevicePlugin", "readIDCard......deviceType：" + deviceType);

		//手机蓝牙开启时才执行
		if (btAdapter.getState() == BluetoothAdapter.STATE_ON){
			if (deviceType == deviceType_kaer_KT8000) {
				BluetoothDevice deviceInfo = devices.get(name); //卡尔也改成每次重新连接，避免隔20分钟左右会断连的问题
				readIDCardKaerKT8000(deviceInfo);
			}
			else if (deviceType == deviceType_kaer_KT8003) {
				BluetoothDevice deviceInfo = devices.get(name); //卡尔也改成每次重新连接，避免隔20分钟左右会断连的问题
				readIDCardKaerKT8003(deviceInfo);
			}
			else if (deviceType == deviceType_senri) {
				BluetoothDevice deviceInfo = devices.get(name); //森锐每次需要重新连接
				readIDCardSenri(deviceInfo);//森锐
			}
			else if (deviceType == deviceType_sensor) {
				readIDCardSensor();
			}
			else if (deviceType == deviceType_hhd) {
				BluetoothDevice deviceInfo = devices.get(name); //恒鸿达每次需要重新连接
				readIDCardHhd(deviceInfo);
			}else if (deviceType == deviceType_senter) {
				BluetoothDevice deviceInfo = devices.get(name);
				readIDCardSenter(deviceInfo);
			}
			else{
				//返回结果
				JSONObject resp = new JSONObject();
				resp.put("respCode", "9998");
				resp.put("respDesc", "该蓝牙读卡器名字未匹配到对应品牌");
				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
			}


		}
		else {
			//返回结果
			JSONObject resp = new JSONObject();
			resp.put("respCode", "0002");
			resp.put("respDesc", "手机蓝牙未打开");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
		}


	}

	/**
	 * 卡尔-读身份证-KT8000
	 * 发现卡尔隔20分钟左右会断连，这边改造下，连接里什么都不做，每次读卡读身份证里都先连接再操作
	 * @throws JSONException
	 */
	private void readIDCardKaerKT8000(BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8000......");
		//返回结果
		JSONObject resp = new JSONObject();

		//如果未连接则先初始化再连接
		if(!kaerClientKt8000.getBtState()){
			//1.卡尔初始化 KT8000
			initKaerDeviceKT8000(this.config.getJSONObject("kt8000"));

			//2.先连接蓝牙
			boolean result = connectDeviceKaerKT8000(deviceInfo); //卡尔-KT8000
			Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8000...connectDeviceKaerKT8000..." + result);

			//如果连接失败直接返回结果
			if(!result){
				resp.put("respCode", "0003");
				resp.put("respDesc", "卡尔kt8000蓝牙读卡器连接失败");

				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
				return;
			}
		}

		//3.读身份证
		IdCardItem idcard = kaerClientKt8000.readIDCard(); //KT8000读卡
		if (idcard.result_code == 0){
			resp.put("respCode", "0000");
			resp.put("respDesc", "卡尔读取身份证成功");

			JSONObject data = new JSONObject();
			data.put("name", (idcard.name).replaceAll(" ", "")); //姓名
			data.put("sexCode", idcard.sex_code);//性别
			data.put("sexName", idcard.sex_code.equals("1") ? "男" : "女");//性别
			data.put("birth", idcard.birth_year + idcard.birth_month + idcard.birth_day);//生日yyyymmdd
			data.put("nationCode", idcard.nation_code);//民族编码
			data.put("nationName", idcard.getNationStr(idcard.nation_code));//民族汉字
			data.put("address", (idcard.address).replaceAll(" ", ""));//住址
			data.put("idNum", idcard.id_num);//身份证号
			data.put("signOffice", (idcard.sign_office).replaceAll(" ", ""));//发证机关
			data.put("usefulStartDate", idcard.useful_s_date_year+idcard.useful_s_date_month+idcard.useful_s_date_day);//有效期开始yyyymmdd
			data.put("usefulEndDate", idcard.useful_e_date_year + idcard.useful_e_date_month + idcard.useful_e_date_day);//有效期结束yyyymmdd
			String picStr = bitmapToBase64(idcard.picBitmap); //照片base64字符串
			data.put("pic", picStr);

			//江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
			if(!TextUtils.isEmpty(this.encryptKey)){
				Log.d("BluetoothDevicePlugin", "encryptKey is ......" + this.encryptKey);
                String nameEncript = encryptIntface.Id2DataEncry(this.encryptKey, (idcard.name).replaceAll(" ", ""));
                String idNumEncript = encryptIntface.Id2DataEncry(this.encryptKey, idcard.id_num);
                String addressEncript = encryptIntface.Id2DataEncry(this.encryptKey, (idcard.address).replaceAll(" ", ""));

                data.put("nameEncript", nameEncript);//姓名加密后
                data.put("idNumEncript", idNumEncript);//身份证号加密后
                data.put("addressEncript", addressEncript);//住址加密后
			}

			resp.put("data", data);
		}
		else if (idcard.result_code == 1){
			resp.put("respCode", "0005");
			resp.put("respDesc", "卡尔读取身份证失败");
		}
		else if (idcard.result_code == 2){
			resp.put("respCode", "0006");
			resp.put("respDesc", "卡尔读取身份证超时");
		}
		else if (idcard.result_code == 3){
			resp.put("respCode", "0007");
			resp.put("respDesc", "卡尔读取身份证错误，连接中断");
		}
		else{
			resp.put("respCode", "0008");
			resp.put("respDesc", "卡尔读取身份证错误，其他错误");
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 卡尔-读身份证-KT8003
	 * 发现卡尔隔20分钟左右会断连，这边改造下，连接里什么都不做，每次读卡读身份证里都先判断是否连接再操作
	 * @throws JSONException
	 */
	private void readIDCardKaerKT8003(BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8003......");
		//返回结果
		JSONObject resp = new JSONObject();

		//如果未连接则先初始化再连接 ,2 已连接，注意不能用kaerClientKt8003.getBtState() != 2判断，20分钟后会报断开服务器，但是却还是2状态
		Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8003...kaerClientKt8003.getBtState()..."+kaerClientKt8003.getBtState());
		//1.卡尔初始化 KT8003
		int status = initKaerDeviceKT8003(this.config.getJSONObject("kt8003"));

		if(status != 0){
			resp.put("respCode", "0003");
			resp.put("respDesc", "卡尔kt8003蓝牙读卡器初始化失败");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
			return;
		}

		//2.先连接蓝牙
		boolean result = connectDeviceKaerKT8003(deviceInfo); //卡尔-KT8003
		Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8003...connectDeviceKaerKT8003..." + result);

		//如果连接失败直接返回结果
		if(!result){
			resp.put("respCode", "0003");
			resp.put("respDesc", "卡尔kt8003蓝牙读卡器连接失败");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
			return;
		}

		//3.读身份证
		IDCardItem idcard = kaerClientKt8003.readCert(); //KT8003读卡
		if (idcard.retCode == 1){
			resp.put("respCode", "0000");
			resp.put("respDesc", "卡尔读取身份证成功");

			JSONObject data = new JSONObject();
			data.put("name", (idcard.partyName).replaceAll(" ", "")); //姓名
			data.put("sexCode", idcard.gender.equals("男") ? "1" : "0");//性别
			data.put("sexName", idcard.gender);//性别
			data.put("birth", idcard.bornDay);//生日yyyymmdd
			data.put("nationCode", "");//民族编码, KT8003 没有编码
			data.put("nationName", idcard.nation);//民族汉字 idcard.getNationStr(idcard.nation)
			data.put("address", (idcard.certAddress).replaceAll(" ", ""));//住址
			data.put("idNum", idcard.certNumber);//身份证号
			data.put("signOffice", (idcard.certOrg).replaceAll(" ", ""));//发证机关
			data.put("usefulStartDate", idcard.effDate);//有效期开始yyyymmdd
			data.put("usefulEndDate", idcard.expDate);//有效期结束yyyymmdd
			String picStr = bitmapToBase64(idcard.picBitmap); //照片base64字符串
			data.put("pic", picStr);

			//江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
			if(!TextUtils.isEmpty(this.encryptKey)){
				Log.d("BluetoothDevicePlugin", "encryptKey is ......" + this.encryptKey);
                String nameEncript = encryptIntface.Id2DataEncry(this.encryptKey, (idcard.partyName).replaceAll(" ", ""));
                String idNumEncript = encryptIntface.Id2DataEncry(this.encryptKey, idcard.certNumber);
                String addressEncript = encryptIntface.Id2DataEncry(this.encryptKey, (idcard.certAddress).replaceAll(" ", ""));

                data.put("nameEncript", nameEncript);//姓名加密后
                data.put("idNumEncript", idNumEncript);//身份证号加密后
                data.put("addressEncript", addressEncript);//住址加密后
			}

			resp.put("data", data);
		}
		else{
			resp.put("respCode", "0008");
			resp.put("respDesc", "卡尔读取身份证错误，其他错误." + CardCode.errorCodeDescription(idcard.retCode));
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 森锐-读身份证
	 * 森锐每次操作都需要重新连接设备然后再操作
	 * 读取成功后的回调函数，在SenriHandler里面注册
	 * @throws JSONException
	 */
	private void readIDCardSenri(BluetoothDevice deviceInfo) throws JSONException {
		Log.d("BluetoothDevicePlugin", "readIDCardSenri......");
		// 返回结果
		JSONObject resp = new JSONObject();

		//1.重新初始化
		this.initSenriDevice(this.config.getJSONObject("senri"));

		//2.连接设备
		String mac = deviceInfo.getAddress();
		boolean isRegisterBT = mBlueReaderHelper.registerBlueCard(mac);
		// senriHandler.sendEmptyMessage(REGISTER_BLUETOOTH);

		//3.蓝牙读身份证
		mBlueReaderHelper.readCard(30);

	}

	/**
	 * 神思-读身份证
	 * @throws JSONException
	 */
	private void readIDCardSensor() throws JSONException{
		Log.d("BluetoothDevicePlugin", "readIDCardSensor......");
		//返回结果
		JSONObject resp = new JSONObject();

		//int iRet = sensorClient.id2ShakeHand();//握手通讯 可以不用关注握手成功与否
		Id2Data returnData = sensorClient.id2ReadCard();//读卡 非加密方式
		if (returnData != null) {
			resp.put("respCode", "0000");
			resp.put("respDesc", "神思读取身份证成功");

			JSONObject data = new JSONObject();
			data.put("name", (returnData.Name).replaceAll(" ", "")); //姓名
			data.put("sexCode", returnData.Gender.equals("男") ? "1" : "0");//性别
			data.put("sexName", returnData.Gender);//性别
			data.put("birth", returnData.BirthDay);//生日yyyymmdd
			data.put("nationCode", returnData.Nation);//民族编码, 神思没有
			data.put("nationName", nationNameFromCode(Integer.valueOf(returnData.Nation)));//民族汉字
			data.put("address", (returnData.Address).replaceAll(" ", ""));//住址
			data.put("idNum", returnData.IdNum);//身份证号
			data.put("signOffice", (returnData.Issue).replaceAll(" ", ""));//发证机关
			data.put("usefulStartDate", returnData.EffDate);//有效期开始yyyymmdd
			data.put("usefulEndDate", returnData.ExpDate);//有效期结束yyyymmdd
			String picStr = bitmapToBase64(returnData.getPic()); //照片base64字符串
			data.put("pic", picStr);

			//江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
			if(!TextUtils.isEmpty(this.encryptKey)){
				Log.d("BluetoothDevicePlugin", "encryptKey is ......" + this.encryptKey);
                String nameEncript = encryptIntface.Id2DataEncry(this.encryptKey, (returnData.Name).replaceAll(" ", ""));
                String idNumEncript = encryptIntface.Id2DataEncry(this.encryptKey, returnData.IdNum);
                String addressEncript = encryptIntface.Id2DataEncry(this.encryptKey, (returnData.Address).replaceAll(" ", ""));

                data.put("nameEncript", nameEncript);//姓名加密后
                data.put("idNumEncript", idNumEncript);//身份证号加密后
                data.put("addressEncript", addressEncript);//住址加密后
			}

			resp.put("data", data);
		}
		else{
			resp.put("respCode", "0005");
			resp.put("respDesc", "神思读取身份证错误");
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 恒鸿达-读身份证
	 * 在registerHhdReadIDCardCallback里注册了读取身份证的回调函数，会返回结果，这边就不返回了
	 * 恒鸿达设备每次读身份证，读iccid，写卡后会自动断掉连接，所以每次操作前都要重新连接 mIdUtil.registerBlueCard(mac);
	 * @param deviceInfo
	 * @throws JSONException
	 */
	private void readIDCardHhd(BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "readIDCardHhd......");

		//1.重新初始化
		initHhdDevice(this.config.getJSONObject("hhd"));

		//2.重新连接
		//mIdUtil.close();//清除之前的连接
		String mac = deviceInfo.getAddress();
		boolean isConnect = mIdUtil.registerBlueCard(mac);//重新连接
		if(isConnect){
			mIdUtil.readCard();
		}
		else{
			//返回结果
			JSONObject resp = new JSONObject();
			resp.put("respCode", "0005");
			resp.put("respDesc", "恒鸿达读取身份证错误，重新建立连接失败");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext); //注意这个上下文
		}

	}

	/**
	 * 信通-读身份证
	 * @param deviceInfo
	 * @throws JSONException
	 *
	 */
	private void readIDCardSenter(BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "readIDCardSenter......");

		if (this.blueaddress == null) {
			if (this.normalCallbackContext != null)
				sendRespmsg("6004", "请选择蓝牙设备，再读卡!", this.normalCallbackContext);
			return;
		}
		if (this.blueaddress.length() <= 0) {
			if (this.normalCallbackContext != null)
				sendRespmsg("6004", "请选择蓝牙设备，再读卡!", this.normalCallbackContext);
			return;
		}

		boolean tag = bluecardHelper_xt.registerBlueCard(this.blueaddress);
		if (tag) {
			XtParm xtParm = new XtParm();
			new BlueReadTask(bluecardHelper_xt,activity, this.handlerSenter_xt, xtParm, this.normalCallbackContext)
					.executeOnExecutor(Executors.newCachedThreadPool());
		} else {
			if (this.normalCallbackContext != null)
				sendRespmsg("6004", "请确认蓝牙设备已经连接，再读卡!", this.normalCallbackContext);
		}
	}

	/**
	 * JSON字段赋值 yd
	 */
	public void sendRespmsg(String respCode, String respDesc, CallbackContext normalCallbackContext) {
		try {
			Log.d("BluetoothDevicePlugin", "sendRespInfo......" + respDesc+"-"+respCode);
			System.out.println("callbackContext......" + respDesc+"-"+respCode);
			JSONObject resp = new JSONObject();
			resp.put("respCode", respCode);
			resp.put("respDesc", respDesc);
			sendRespInfo(resp, normalCallbackContext);
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}


	/**
	 * 读sim卡 iccid
	 * @param param
	 * @param callbackContext
	 * @throws JSONException
	 */
	private void readICCID(JSONObject param, CallbackContext callbackContext) throws JSONException{
		Log.d("BluetoothDevicePlugin", "readICCID......");

		//设置cordova调用上下文
		this.normalCallbackContext = callbackContext;

		String name = param.getString("name"); //获取蓝牙设备的名字
		int deviceType = deviceTypeFromName(name); //根据名字获取设备类型
		Log.d("BluetoothDevicePlugin", "readICCID......deviceType：" + deviceType);

		//手机蓝牙开启时才执行
		if (btAdapter.getState() == BluetoothAdapter.STATE_ON){
			if (deviceType == deviceType_kaer_KT8000) {
				BluetoothDevice deviceInfo = devices.get(name); //卡尔也改成每次重新连接，避免隔20分钟左右会断连的问题
				readICCIDKaerKT8000(deviceInfo);
			}
			else if (deviceType == deviceType_kaer_KT8003) {
				BluetoothDevice deviceInfo = devices.get(name); //卡尔也改成每次重新连接，避免隔20分钟左右会断连的问题
				readICCIDKaerKT8003(deviceInfo);
			}
			else if (deviceType == deviceType_senri) {
				BluetoothDevice deviceInfo = devices.get(name); //森锐每次需要重新连接
				readICCIDSenri(deviceInfo); //森锐
			}
			else if (deviceType == deviceType_sensor) {
				readICCIDSensor();
			}
			else if (deviceType == deviceType_hhd) {
				BluetoothDevice deviceInfo = devices.get(name); //恒鸿达每次需要重新连接
				readICCIDHhd(deviceInfo);
			}
			else if(deviceType == deviceType_senter) {
				BluetoothDevice deviceInfo = devices.get(name);
				readICCIDSenter(deviceInfo);
			}
			else{
				//返回结果
				JSONObject resp = new JSONObject();
				resp.put("respCode", "9998");
				resp.put("respDesc", "该蓝牙读卡器名字未匹配到对应品牌");
				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
			}
		}
		else {
			//返回结果
			JSONObject resp = new JSONObject();
			resp.put("respCode", "0002");
			resp.put("respDesc", "手机蓝牙未打开");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
		}

	}

	/**
	 * 卡尔-读iccid
	 * 发现卡尔隔20分钟左右会断连，这边改造下，连接里什么都不做，每次读卡读身份证里都先连接再操作
	 * @throws JSONException
	 */
	private void readICCIDKaerKT8000(BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "readICCIDKaer......");
		//返回结果
		JSONObject resp = new JSONObject();

		//如果未连接则先初始化再连接
		if(!kaerClientKt8000.getBtState()){
			//1.卡尔初始化 KT8000
			initKaerDeviceKT8000(this.config.getJSONObject("kt8000"));

			//2.先连接蓝牙
			boolean result = connectDeviceKaerKT8000(deviceInfo); //卡尔-KT8000
			Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8000...connectDeviceKaerKT8000..." + result);

			//如果连接失败直接返回结果
			if(!result){
				resp.put("respCode", "0003");
				resp.put("respDesc", "卡尔kt8000蓝牙读卡器连接失败");

				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
				return;
			}
		}

		//3.读取iccid
		String iccid = kaerClientKt8000.readICCID();
		if(iccid==null || iccid.equals("")){
			resp.put("respCode", "0009");
			resp.put("respDesc", "卡尔读取iccid结果为空");
		}
		else{
			byte [] resultByte = hexStringToByte(iccid);
			int resultLen = (int)resultByte[6];
			if(resultLen==1){
				int error = (int)resultByte[7];
				switch (error) {
				case 1:
					resp.put("respCode", "0010");
					resp.put("respDesc", "卡尔读取iccid错误,sim卡未插入");
					break;
				case 2:
					resp.put("respCode", "0011");
					resp.put("respDesc", "卡尔读取iccid错误,sim卡插入但是不识别");
					break;
				case 4:
					resp.put("respCode", "0012");
					resp.put("respDesc", "卡尔读取iccid错误,sim卡插入但还未成功读取");
					break;
				default:
					resp.put("respCode", "0013");
					resp.put("respDesc", "卡尔读取iccid错误,其他错误");
					break;
				}
			}else{
				byte []tmp = new byte[resultLen];
				for(int i=0;i<resultLen;i++){
					tmp[i] = resultByte[7+i];
				}
				//成功返回
				resp.put("respCode", "0000");
				resp.put("respDesc", "卡尔读取iccid成功");

				JSONObject data = new JSONObject();
				String iccidStr = bytesToASCString(tmp);
				data.put("iccid", iccidStr);
				resp.put("data", data);

			}
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 卡尔-读iccid-KT8003
	 * 发现卡尔隔20分钟左右会断连，这边改造下，连接里什么都不做，每次读卡读身份证里都先判断连接再操作
	 * @throws JSONException
	 */
	private void readICCIDKaerKT8003(BluetoothDevice deviceInfo) throws JSONException {
		Log.d("BluetoothDevicePlugin", "readICCIDKaerKT8003......");
		// 返回结果
		JSONObject resp = new JSONObject();

		//如果未连接则先初始化再连接 ,2 已连接，注意不能用kaerClientKt8003.getBtState() != 2判断，20分钟后会报断开服务器，但是却还是2状态
		Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8003...kaerClientKt8003.getBtState()..."+kaerClientKt8003.getBtState());
		//1.卡尔初始化 KT8003
		int status = initKaerDeviceKT8003(this.config.getJSONObject("kt8003"));

		if(status != 0){
			resp.put("respCode", "0003");
			resp.put("respDesc", "卡尔kt8003蓝牙读卡器初始化失败");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
			return;
		}

		//2.先连接蓝牙
		boolean result = connectDeviceKaerKT8003(deviceInfo); //卡尔-KT8003
		Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8003...connectDeviceKaerKT8003..." + result);

		//如果连接失败直接返回结果
		if(!result){
			resp.put("respCode", "0003");
			resp.put("respDesc", "卡尔kt8003蓝牙读卡器连接失败");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
			return;
		}

		//3.读取iccid
		String iccid = kaerClientKt8003.readICCID();
		if (TextUtils.isEmpty(iccid) || iccid.length() < 10) {
			resp.put("respCode", "0009");
			resp.put("respDesc", "卡尔读取iccid结果为空或者长度小于10");
		} else {
			// 成功返回
			resp.put("respCode", "0000");
			resp.put("respDesc", "卡尔读取iccid成功");

			JSONObject data = new JSONObject();
			data.put("iccid", iccid);
			resp.put("data", data);
		}

		// 返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 森锐-读iccid
	 * 森锐设备每次操作都需要重连，操作完会自动断开连接
	 * @throws JSONException
	 */
	private void readICCIDSenri(BluetoothDevice deviceInfo) throws JSONException {
		Log.d("BluetoothDevicePlugin", "readICCIDSenri......");
		// 返回结果
		JSONObject resp = new JSONObject();

		//1.重新初始化
		this.initSenriDevice(this.config.getJSONObject("senri"));

		//2.连接设备
		String mac = deviceInfo.getAddress();
		boolean isRegisterBT = mBlueReaderHelper.registerBlueCard(mac);

		//3.读sim卡信息
		IDReadCardInfo result = mBlueReaderHelper.readCardInfo();
		String cardType = result.CARDTYPE; // 0=白卡; 1=成卡; -1=阅读器错误
		String iccid = result.ICCID;

		if (cardType.equals("-1")) {
			resp.put("respCode", "0009");
			resp.put("respDesc", "森锐读取sim卡错误");
		} else {
			// 成功返回
			resp.put("respCode", "0000");
			resp.put("respDesc", "森锐读取iccid成功");

			JSONObject data = new JSONObject();
			data.put("iccid", iccid);
			resp.put("data", data);
		}

		// 返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 神思-读iccid
	 * 注意神思每次读完身份证，要拿起来重放才能读第二次
	 * @throws JSONException
	 */
	private void readICCIDSensor() throws JSONException{
		Log.d("BluetoothDevicePlugin", "readICCIDSensor......");
		//返回结果
		JSONObject resp = new JSONObject();

		HashMap<String, Object> simHm = sensorClient.readICCID();
		int ST = (Integer) simHm.get("ST"); //错误码
		int ICCID_LEN = (Integer) simHm.get("ICCID_LEN");
		String ICCID = (String) simHm.get("ICCID");
		Log.d("BluetoothDevicePlugin", "readICCIDSensor......ST：" + ST + ", ICCID_LEN:"+ICCID_LEN + ", ICCID:" + ICCID);
		if(ST==0){
			if(ICCID_LEN>0){
				//成功返回
				resp.put("respCode", "0000");
				resp.put("respDesc", "神思读取iccid成功");

				JSONObject data = new JSONObject();
				data.put("iccid", ICCID);
				resp.put("data", data);
			}else{
				resp.put("respCode", "0009");
				resp.put("respDesc", "神思读取iccid结果为空");
			}
		}else if(ST==-9){
			resp.put("respCode", "0010");
			resp.put("respDesc", "神思读取iccid错误,该型号设备不支持此功能");
		}else{
			resp.put("respCode", "0011");
			resp.put("respDesc", "神思读取iccid错误,命令执行失败");
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 恒鸿达-读iccid
	 * @param deviceInfo
	 * @throws JSONException
	 */
	private void readICCIDHhd(BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "readICCIDHhd......");
		//返回结果
		JSONObject resp = new JSONObject();

		//1.重新初始化
		initHhdDevice(this.config.getJSONObject("hhd"));

		//2.重新连接
		//mIdUtil.close();//清除之前的连接
		String mac = deviceInfo.getAddress();
		boolean isConnect = mIdUtil.registerBlueCard(mac);//重新连接
		if(isConnect){
			byte[] iccid = new byte[20];//iccid 固定长度20位
			byte[] iccidb_len = new byte[1];
			int ret = mIdUtil.Mini_sim_iccid_get_mid(iccidb_len, iccid);
			if(ret == -1)
			{
				resp.put("respCode", "0009");
				resp.put("respDesc", "恒鸿达读取iccid失败");
			}
			else{
				//成功返回
				resp.put("respCode", "0000");
				resp.put("respDesc", "恒鸿达读取iccid成功");
				//String iccidStr = bytesToASCString(iccid);

				JSONObject data = new JSONObject();
				String iccidStr = new String(iccid);
				data.put("iccid", iccidStr);
				resp.put("data", data);
			}
		}
		else{
			resp.put("respCode", "0005");
			resp.put("respDesc", "恒鸿达读取身份证错误，重新建立连接失败");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 信通-读iccid
	 * @param deviceInfo
	 * @throws JSONException
	 */
	private void readICCIDSenter(BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "readICCIDSenter......");

		JSONObject resp = new JSONObject();
		if (this.blueaddress == null) {
			sendRespmsg("6002", "请选择蓝牙设备，再读卡!", this.normalCallbackContext);
			return;
		}

		if (this.blueaddress.length() <= 0) {
			sendRespmsg("6002", "请选择蓝牙设备，再读卡!", this.normalCallbackContext);
			return;
		}

		if (bluecardHelper_xt.registerBlueCard(this.blueaddress)) {
			byte[] iccid = new byte[128];
			int icardtype = bluecardHelper_xt.readSimICCID(iccid);

			String strcardtype = "";
			switch (icardtype) {
				case -1:
					strcardtype = "读卡失败";
					break;
				case 1:
					strcardtype = "成卡";
					break;
				case 0:
					strcardtype = "白卡";
					break;
			}
			/****************如果是白卡则继续血卡**************/
//      if (icardtype == 0) {
//        // SMSC_serverDialog("输入短信中心号码");
//        SMSC_server(et_imsinumber, et_mmsnumber, normalCallbackContext);
//
//      }
			int length = getValidLength(iccid);
			byte[] bb = new byte[length];
			System.arraycopy(iccid, 0, bb, 0, length);
			String result = new String(iccid).toString().replace("\u0000","");
			if (strcardtype.equals("读卡失败")) {
				resp.put("respCode", "9999");
				resp.put("respDesc", "读卡失败");
			} else {
				resp.put("respCode", "0000");
				resp.put("respDesc", "信通读取iccid成功");
				JSONObject data = new JSONObject();
				data.put("iccid", result);
				data.put("strcardtype", strcardtype);
				resp.put("data", data);
			}
			sendRespInfo(resp, this.normalCallbackContext);
			Log.d("writeCardBlueTooth", new String(iccid) + " 卡类型: " + strcardtype);
		}

	}

	/**
	 * 校验iccid的长度
	 * @param bytes
	 * @return
	 * by yd
	 */
	private int getValidLength(byte[] bytes) {
		int i = 0;
		if (null == bytes || 0 == bytes.length)
			return i;
		for (; i < bytes.length; i++) {
			if (bytes[i] == '\0')
				break;
		}
		return i + 1;
	}



	/**
	 * 写sim卡 imsi，和 写短信中心smsc
	 * 短信中心smsc 11位不要+86，但是入参就算传了+86也没事，代码里会replace掉
	 * @param param
	 * @param callbackContext
	 * @throws JSONException
	 */
	private void writeSim(JSONObject param, CallbackContext callbackContext) throws JSONException{
		Log.d("BluetoothDevicePlugin", "writeSim......");

		//设置cordova调用上下文
		this.normalCallbackContext = callbackContext;

		String name = param.getString("name"); //获取蓝牙设备的名字
		int deviceType = deviceTypeFromName(name); //根据名字获取设备类型
		Log.d("BluetoothDevicePlugin", "writeSim......deviceType：" + deviceType);

		//手机蓝牙开启时才执行
		if (btAdapter.getState() == BluetoothAdapter.STATE_ON){
			if (deviceType == deviceType_kaer_KT8000) {
				BluetoothDevice deviceInfo = devices.get(name); //卡尔也改成每次重新连接，避免隔20分钟左右会断连的问题
				writeSimKaerKT8000(param, deviceInfo);
			}
			else if (deviceType == deviceType_kaer_KT8003) {
				BluetoothDevice deviceInfo = devices.get(name); //卡尔也改成每次重新连接，避免隔20分钟左右会断连的问题
				writeSimKaerKT8003(param, deviceInfo);
			}
			else if (deviceType == deviceType_senri) {
				BluetoothDevice deviceInfo = devices.get(name); //森锐每次需要重新连接
				writeSimSenri(param, deviceInfo); //森锐
			}
			else if (deviceType == deviceType_sensor) {
				writeSimSensor(param);
			}
			else if (deviceType == deviceType_hhd) {
				BluetoothDevice deviceInfo = devices.get(name); //恒鸿达每次需要重新连接
				writeSimHhd(param, deviceInfo);
			}
			else if (deviceType == deviceType_senter) {
				BluetoothDevice deviceInfo = devices.get(name);
				writeSimSenter(param, deviceInfo);
			}


			else{
				//返回结果
				JSONObject resp = new JSONObject();
				resp.put("respCode", "9998");
				resp.put("respDesc", "该蓝牙读卡器名字未匹配到对应品牌");
				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
			}


		}
		else {
			//返回结果
			JSONObject resp = new JSONObject();
			resp.put("respCode", "0002");
			resp.put("respDesc", "手机蓝牙未打开");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
		}


	}


	/**
	 * 卡尔-写imsi和写短信中心smsc
	 * 先写imsi，写成功了再写smsc
	 * 发现卡尔隔20分钟左右会断连，这边改造下，连接里什么都不做，每次读卡读身份证里都先连接再操作
	 *
	 * @param param
	 * @throws JSONException
	 */
	private void writeSimKaerKT8000(JSONObject param, BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "writeSimKaer......");
		//返回结果
		JSONObject resp = new JSONObject();

		//如果未连接则先初始化再连接
		if(!kaerClientKt8000.getBtState()){
			//1.卡尔初始化 KT8000
			initKaerDeviceKT8000(this.config.getJSONObject("kt8000"));

			//2.先连接蓝牙
			boolean result = connectDeviceKaerKT8000(deviceInfo); //卡尔-KT8000
			Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8000...connectDeviceKaerKT8000..." + result);

			//如果连接失败直接返回结果
			if(!result){
				resp.put("respCode", "0003");
				resp.put("respDesc", "卡尔kt8000蓝牙读卡器连接失败");

				//返回结果
				sendRespInfo(resp, this.normalCallbackContext);
				return;
			}
		}

		//3.写卡
		//imsi1和imsi2取一样的值
		String imsi1 = param.getString("imsi"); //15位imsi号
		byte[] imsi1Bytes = imsi1.getBytes();

		if(imsi1Bytes == null || imsi1Bytes.length!=15){
			resp.put("respCode", "0014");
			resp.put("respDesc", "卡尔写imsi失败，imsi为空或者长度不是15");
		}
		else{
			int writeImsiRes = kaerClientKt8000.WriteIMSI(imsi1Bytes, imsi1Bytes);//2个imsi写一样的值
			if(writeImsiRes == 1){
				//imsi 写成功了再写smsc短信中心
				byte index = 1;//Index 短信中心索引，从1 开始
				String smsc = param.getString("smsc").replaceAll("\\+86", ""); //11位短信中心号，不要+86
				int writeSmscRes = kaerClientKt8000.WriteSMSC(smsc, index);
				if(writeSmscRes == 1){
					resp.put("respCode", "0000");
					resp.put("respDesc", "卡尔写imsi成功, 写smsc成功");
				}else{
					int error = writeSmscRes;
					switch (error) {
					case 0:
						resp.put("respCode", "0015");
						resp.put("respDesc", "卡尔写imsi成功,写smsc失败");
						break;
					case 2:
						resp.put("respCode", "0016");
						resp.put("respDesc", "卡尔写imsi成功,写smsc失败,卡未插入");
						break;
					case 3:
						resp.put("respCode", "0017");
						resp.put("respDesc", "卡尔写imsi成功,写smsc失败,不识别的SIM卡");
						break;
					case 4:
						resp.put("respCode", "0018");
						resp.put("respDesc", "卡尔写imsi成功,写smsc失败,sim卡插入但还未初始化");
						break;
					default:
						break;
					}
				}
			}else{
				int error = writeImsiRes;
				switch (error) {
				case 0:
					resp.put("respCode", "0015");
					resp.put("respDesc", "卡尔写imsi失败");
					break;
				case 2:
					resp.put("respCode", "0016");
					resp.put("respDesc", "卡尔写imsi失败,卡未插入");
					break;
				case 3:
					resp.put("respCode", "0017");
					resp.put("respDesc", "卡尔写imsi失败,不识别的SIM卡");
					break;
				case 4:
					resp.put("respCode", "0018");
					resp.put("respDesc", "卡尔写imsi失败,sim卡插入但还未初始化");
					break;
				default:
					break;
				}
			}
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 卡尔-写imsi和写短信中心smsc-KT8003
	 * 短信中心 不要 +86
	 * 先写imsi，写成功了再写smsc
	 * @param param
	 * @throws JSONException
	 */
	private void writeSimKaerKT8003(JSONObject param, BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "writeSimKaerKT8003......");
		//返回结果
		JSONObject resp = new JSONObject();

		//如果未连接则先初始化再连接 ,2 已连接，注意不能用kaerClientKt8003.getBtState() != 2判断，20分钟后会报断开服务器，但是却还是2状态
		Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8003...kaerClientKt8003.getBtState()..."+kaerClientKt8003.getBtState());
		//1.卡尔初始化 KT8003
		int status = initKaerDeviceKT8003(this.config.getJSONObject("kt8003"));

		if(status != 0){
			resp.put("respCode", "0003");
			resp.put("respDesc", "卡尔kt8003蓝牙读卡器初始化失败");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
			return;
		}

		//2.先连接蓝牙
		boolean result = connectDeviceKaerKT8003(deviceInfo); //卡尔-KT8003
		Log.d("BluetoothDevicePlugin", "readIDCardKaerKT8003...connectDeviceKaerKT8003..." + result);

		//如果连接失败直接返回结果
		if(!result){
			resp.put("respCode", "0003");
			resp.put("respDesc", "卡尔kt8003蓝牙读卡器连接失败");
			//返回结果
			sendRespInfo(resp, this.normalCallbackContext);
			return;
		}

		//imsi1和imsi2取一样的值
		String imsi1 = param.getString("imsi"); //15位imsi号
		byte[] imsi1Bytes = imsi1.getBytes();

		if(imsi1Bytes == null || imsi1Bytes.length!=15){
			resp.put("respCode", "0014");
			resp.put("respDesc", "卡尔写imsi失败，imsi为空或者长度不是15");
		}
		else{
			int writeImsiRes = kaerClientKt8003.WriteIMSI(imsi1Bytes, imsi1Bytes);//2个imsi写一样的值
			if(writeImsiRes == 1){
				//imsi 写成功了再写smsc短信中心
				byte index = 1;//Index 短信中心索引，从1 开始
				String smsc = param.getString("smsc").replaceAll("\\+86", ""); //11位短信中心号，不要+86
				int writeSmscRes = kaerClientKt8003.WriteSMSC(smsc, index);
				if(writeSmscRes == 1){
					resp.put("respCode", "0000");
					resp.put("respDesc", "卡尔写imsi成功, 写smsc成功");
				}else{
					resp.put("respCode", "0015");
					resp.put("respDesc", "卡尔写imsi成功, 卡尔写smsc失败," + CardCode.errorCodeDescription(writeSmscRes));
				}
			}else{
				resp.put("respCode", "0015");
				resp.put("respDesc", "卡尔写imsi失败," + CardCode.errorCodeDescription(writeImsiRes));
			}
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 森锐-写imsi和写短信中心smsc
	 * 每次需要重新连接
	 * 先写imsi，写成功了再写smsc
	 * 注意 森锐设备 短信中心 不要 +86
	 * @param param
	 * @param deviceInfo
	 * @throws JSONException
	 */
	private void writeSimSenri(JSONObject param, BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "writeSimSenri......");
		//返回结果
		JSONObject resp = new JSONObject();

		//1.重新初始化
		this.initSenriDevice(this.config.getJSONObject("senri"));

		//2.连接设备
		String mac = deviceInfo.getAddress();
		boolean isRegisterBT = mBlueReaderHelper.registerBlueCard(mac);

		//3.写卡
		if(isRegisterBT){
			//
			String imsi = param.getString("imsi"); //15位imsi号
			String smsc = param.getString("smsc").replaceAll("\\+86", ""); //11位短信中心号，不要+86

			if(imsi.length() !=15){
				resp.put("respCode", "0014");
				resp.put("respDesc", "森锐写imsi失败，imsi为空或者长度不是15");
			}
			else{
				//写imsi 和短信中心
				boolean result = mBlueReaderHelper.writeSimCard(imsi, smsc);
				if (result) {
					resp.put("respCode", "0000");
					resp.put("respDesc", "森锐写imsi成功, 写smsc成功");
				}
				else{
					resp.put("respCode", "0005");
					resp.put("respDesc", "森锐写imsi 和 smsc失败");
				}
			}
		}
		else{
			resp.put("respCode", "0005");
			resp.put("respDesc", "森锐写imsi 和 smsc失败，重新建立连接失败");
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 神思-写imsi和写短信中心smsc
	 * 先写imsi，写成功了再写smsc
	 * @param param
	 * @throws JSONException
	 */
	private void writeSimSensor(JSONObject param) throws JSONException{
		Log.d("BluetoothDevicePlugin", "writeSimSensor......");
		//返回结果
		JSONObject resp = new JSONObject();

		//imsi1和imsi2取一样的值
		String imsi1 = param.getString("imsi"); //15位imsi号
		byte[] imsi1Bytes = imsi1.getBytes();

		if(imsi1Bytes == null || imsi1Bytes.length!=15){
			resp.put("respCode", "0014");
			resp.put("respDesc", "神思写imsi失败，imsi为空或者长度不是15");
		}
		else{
			int ret1 = sensorClient.writeBlankSim(imsi1Bytes, imsi1.length(), imsi1Bytes, imsi1.length());
			if(ret1 == 0){
				String smsc = param.getString("smsc").replaceAll("\\+86", ""); //11位短信中心号，不要+86
				int ret2 = sensorClient.writeSmsCenter(smsc.getBytes(), smsc.length());
				if(ret2 == 0){
					resp.put("respCode", "0000");
					resp.put("respDesc", "神思写imsi成功, 写smsc成功");
				}else if(ret2 == -9){
					resp.put("respCode", "0015");
					resp.put("respDesc", "神思写imsi成功, 写smsc失败, 该设备不支持此功能");
				}else{
					resp.put("respCode", "0016");
					resp.put("respDesc", "神思写imsi成功, 写smsc失败, 其他错误");
				}
			}else if(ret1 == -9){
				resp.put("respCode", "0015");
				resp.put("respDesc", "神思写imsi失败, 该设备不支持此功能");
			}else{
				resp.put("respCode", "0016");
				resp.put("respDesc", "神思写imsi失败，其他错误");
			}
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 恒鸿达-写imsi和写短信中心smsc
	 * 每次需要重新连接
	 * 先写imsi，写成功了再写smsc
	 * 注意 恒鸿达设备 短信中心 要 +86
	 * @param param
	 * @param deviceInfo
	 * @throws JSONException
	 */
	private void writeSimHhd(JSONObject param, BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "writeSimHhd......");
		//返回结果
		JSONObject resp = new JSONObject();

		//1.重新初始化
		initHhdDevice(this.config.getJSONObject("hhd"));

		//2.重新连接
		//mIdUtil.close();//清除之前的连接
		String mac = deviceInfo.getAddress();
		boolean isConnect = mIdUtil.registerBlueCard(mac);//重新连接
		if(isConnect){
			//imsi1和imsi2取一样的值
			String imsi1 = param.getString("imsi"); //15位imsi号
			byte[] imsi1Bytes = imsi1.getBytes();

			if(imsi1Bytes == null || imsi1Bytes.length!=15){
				resp.put("respCode", "0014");
				resp.put("respDesc", "恒鸿达写imsi失败，imsi为空或者长度不是15");
			}
			else{
				//写imsi
				int ret1 = mIdUtil.Mini_sim_imsi_write_mid(imsi1.getBytes(),
						imsi1.getBytes());
				//imsi写成功后写短信中心
				if (ret1 > 0) {
					boolean isConnect2 = mIdUtil.registerBlueCard(mac);//注意要再次重新连接
					if(isConnect2){
						String smsc = param.getString("smsc"); //14位短信中心号，要+86,如果没有传则加上
						if(smsc.indexOf("+86") < 0){
							smsc = "+86" + smsc;
						}
						int ret2 = mIdUtil.Mini_sim_smsc_write_mid(smsc.getBytes());
						if (ret2 > 0) {
							resp.put("respCode", "0000");
							resp.put("respDesc", "恒鸿达写imsi成功, 写smsc成功");
						}
						else{
							resp.put("respCode", "0016");
							resp.put("respDesc", "恒鸿达写imsi成功, 写smsc失败,其他错误");
						}
					}
					else{
						resp.put("respCode", "0005");
						resp.put("respDesc", "恒鸿达写imsi成功, 写smsc失败，重新建立连接失败");
					}

				}
				else{
					resp.put("respCode", "0016");
					resp.put("respDesc", "恒鸿达写imsi失败，其他错误");
				}

			}
		}
		else{
			resp.put("respCode", "0005");
			resp.put("respDesc", "恒鸿达写imsi失败，重新建立连接失败");
//			//返回结果
//			sendRespInfo(resp, this.normalCallbackContext);
		}

		//返回结果
		sendRespInfo(resp, this.normalCallbackContext);
	}

	/**
	 * 信通写卡
	 * @param param
	 * @param deviceInfo
	 */
	private void writeSimSenter(JSONObject param, BluetoothDevice deviceInfo) throws JSONException{
		Log.d("BluetoothDevicePlugin", "writeSimSenter......");

		String et_imsinumber = param.getString("imsi");
		String et_mmsnumber = param.getString("smsc").replaceAll("\\+86", "");

		if (et_mmsnumber == null) {
			sendRespmsg("6003", "请输入短信中心号码，再写卡!", this.normalCallbackContext);
			return;
		}

		if (et_mmsnumber.length() <= 0) {
			sendRespmsg("6003", "请输入短信中心号码，再写卡!", this.normalCallbackContext);
			return;
		}

		if (et_imsinumber == null) {
			sendRespmsg("6003", "请输入IMSI，再写卡!", this.normalCallbackContext);
			return;
		}

		if (et_imsinumber.length() <= 0) {
			sendRespmsg("6003", "请输入IMSI，再写卡!", this.normalCallbackContext);
			return;
		}

		if (this.blueaddress == null) {
			sendRespmsg("6003", "请选择蓝牙设备，再读卡!", this.normalCallbackContext);
			return;
		}

		if (this.blueaddress.length() <= 0) {
			sendRespmsg("6003", "请选择蓝牙设备，再读卡!", this.normalCallbackContext);
			return;
		}
		// TODO Auto-generated method stub
		if (bluecardHelper_xt.registerBlueCard(this.blueaddress)) {
			int bret = bluecardHelper_xt.writeSimCard(et_imsinumber, et_mmsnumber);
			String strts = "";
			String id = "";
			switch (bret) {
				case 1:
					id = "0000";
					strts = "写卡成功!";
					break;
				case -1:
					id = "9999";
					strts = "短信中心号码不对";
					break;
				case 0:
					id = "9999";
					strts = "写卡失败!";
					break;
				default:
					id = "9999";
					strts = "写卡失败!";
					break;
			}
			sendRespmsg(id, strts, this.normalCallbackContext);
		}
	}




	/**
	 * 根据设备名称前缀，判断是什么品牌的蓝牙设备，用于调用不同的sdk
	 * 0:其他 1：卡尔 2：森锐 3：神思 4：恒鸿达
	 * @param name
	 * @return
	 */
	private int deviceTypeFromName(String name){

		if(name == null || name.equals("")){
			return deviceType_other;
		}
		else if(TextUtils.indexOf(name, "KT8000") == 0){
			return deviceType_kaer_KT8000;
		}
		else if(TextUtils.indexOf(name, "KT8003") == 0){
			return deviceType_kaer_KT8003;
		}
		else if(TextUtils.indexOf(name, "SR") == 0){
			return deviceType_senri;
		}
		else if(TextUtils.indexOf(name, "SS") == 0){
			return deviceType_sensor;
		}
		else if(TextUtils.indexOf(name, "HOD") == 0){
			return deviceType_hhd;
		}
		else if (TextUtils.indexOf(name, "ST") == 0) {
			return deviceType_senter;
		}
		else{
			return deviceType_other;
		}
	}

    /**
     * bitmap转为base64
     * @param bitmap
     * @return
     */
    public String bitmapToBase64(Bitmap bitmap) {

        String result = null;
        ByteArrayOutputStream baos = null;
        try {
            if (bitmap != null) {
                baos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);

                baos.flush();
                baos.close();

                byte[] bitmapBytes = baos.toByteArray();
                result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.flush();
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        result = result.replace("\n", "");
        result = result.replace("\r", "");
        return result;
    }

    /**
     * 根据民族编码转换成名称
     * @param nationCode
     * @return
     */
    private String nationNameFromCode(int nationCode){
        switch (nationCode) {
            case 1:
                return "汉族";
            case 2:
                return "蒙古族";
            case 3:
                return "回族";
            case 4:
                return "藏族";
            case 5:
                return "维吾尔族";
            case 6:
                return "苗族";
            case 7:
                return "彝族";
            case 8:
                return "壮族";
            case 9:
                return "布依族";
            case 10:
                return "朝鲜族";
            case 11:
                return "满族";
            case 12:
                return "侗族";
            case 13:
                return "瑶族";
            case 14:
                return "白族";
            case 15:
                return "土家族";
            case 16:
                return "哈尼族";
            case 17:
                return "哈萨克族";
            case 18:
                return "傣族";
            case 19:
                return "黎族";
            case 20:
                return "傈僳族";
            case 21:
                return "佤族";
            case 22:
                return "畲族";
            case 23:
                return "高山族";
            case 24:
                return "拉祜族";
            case 25:
                return "水族";
            case 26:
                return "东乡族";
            case 27:
                return "纳西族";
            case 28:
                return "景颇族";
            case 29:
                return "柯尔克孜族";
            case 30:
                return "土族";
            case 31:
                return "达斡尔族";
            case 32:
                return "仫佬族";
            case 33:
                return "羌族";
            case 34:
                return "布朗族";
            case 35:
                return "撒拉族";
            case 36:
                return "毛难族";
            case 37:
                return "仡佬族";
            case 38:
                return "锡伯族";
            case 39:
                return "阿昌族";
            case 40:
                return "普米族";
            case 41:
                return "塔吉克族";
            case 42:
                return "怒族";
            case 43:
                return "乌孜别克族";
            case 44:
                return "俄罗斯族";
            case 45:
                return "鄂温克族";
            case 46:
                return "崩龙族";
            case 47:
                return "保安族";
            case 48:
                return "裕固族";
            case 49:
                return "京族";
            case 50:
                return "塔塔尔族";
            case 51:
                return "独龙族";
            case 52:
                return "鄂伦春族";
            case 53:
                return "赫哲族";
            case 54:
                return "门巴族";
            case 55:
                return "珞巴族";
            case 56:
                return "基诺族";
            default:
                return "其他";
        }
    }

    private byte[] hexStringToByte(String hex_str){

    	byte[] data_byte = new byte[hex_str.length()/2];
    	int byte_len = 0;
    	for (int i = 0;i < hex_str.length();i += 2){
    		data_byte[byte_len ++] = HexToByte(hex_str.charAt(i),hex_str.charAt(i+1));
    	}
    	return data_byte;
    }

    private String bytesToASCString(byte[] src) {
		int len = src.length;

		if (src == null || len <= 0) {
			return null;
		}
		char[] result = new char[len];
		for (int i = 0; i < len; i++) {
			result[i] = (char) src[i];
		}

		return String.valueOf(result);
	}

    private byte HexToByte(char hex1, char hex2)
    {
	    byte result = 0;
	    for(int i = 0;i < 2;i++)
	    {
		    char c;
		    if (i == 0)
		    	c = hex1;
		    else
		    	c = hex2;
		    byte b = 0;
		    switch (c)
		    {
			    case '0':
			    case '1':
			    case '2':
			    case '3':
			    case '4':
			    case '5':
			    case '6':
			    case '7':
			    case '8':
			    case '9':
				    b = (byte)(c - '0');
				    break;
			    case 'A':
			    case 'B':
			    case 'C':
			    case 'D':
			    case 'E':
			    case 'F':
				    b = (byte)(10 + c - 'A');
				    break;
			    case 'a':
			    case 'b':
			    case 'c':
			    case 'd':
			    case 'e':
			    case 'f':
				    b = (byte)(10 + c - 'a');
				    break;
		    }
		    if (i == 0)
		    {
		    	b = (byte)(b * 16);
		    }
		    result += b;
	    }
	    return result;
    }

	/**
	 * 恒鸿达-工具函数-域名翻译成ip
	 * @param host
	 * @return
	 */
	public static String GetInetAddress(String  host){
	    String IPAddress = "";
	    InetAddress ReturnStr1 = null;
	    try {
	        ReturnStr1 = java.net.InetAddress.getByName(host);
	        IPAddress = ReturnStr1.getHostAddress();
	    } catch (UnknownHostException e) {
	        e.printStackTrace();
	        return  IPAddress;
	    }
	    return IPAddress;
	}

	/**
	 * 返回消息给前端，这边全都算做success，只是通过respCode来区分是否成功
	 * 返回的是json字符串，跟ios统一
	 * @param resp
	 * @param callbackContext
	 */
	private void sendRespInfo(JSONObject resp, CallbackContext callbackContext){
		String message = resp.toString(); //json转换成字符串
		Log.d("BluetoothDevicePlugin", "sendRespInfo......" + message);

		//成功回调
		//callbackContext.success(message);

		//为了一次调用能多次返回结果给前端，得用下面的方式返回结果,
		//PluginResult plugin = new PluginResult(PluginResult.Status.OK, message);
		PluginResult plugin = new PluginResult(PluginResult.Status.OK, resp);
		plugin.setKeepCallback(true);
        callbackContext.sendPluginResult(plugin);
	}

    /**
     * 森锐-内部类，消息handle,包括绑定蓝牙消息、绑定OTG消息、读身份证结果返回消息
     */
    class SenriHandler extends Handler {

//        @SuppressLint("HandlerLeak")
//        MyHandler(Activity activity) {
//            this.activity = activity;
//        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                //成功
                case ConsantHelper.READ_CARD_SUCCESS:
                	senriHandleReturnSuccessMsg(msg);
                    break;

                //错误-1
                case ConsantHelper.READ_CARD_NO_READ:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-2
                case ConsantHelper.READ_CARD_BUSY:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-3
                case ConsantHelper.READ_CARD_NET_ERR:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-4
                case ConsantHelper.READ_CARD_NO_CARD:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-5
                case ConsantHelper.READ_CARD_SAM_ERR:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-6
                case ConsantHelper.READ_CARD_OTHER_ERR:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-7
                case ConsantHelper.READ_CARD_NEED_TRY:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-8
                case ConsantHelper.READ_CARD_OPEN_FAILED:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-9
                case ConsantHelper.READ_CARD_NO_CONNECT:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-10
                case ConsantHelper.READ_CARD_NO_SERVER:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-11
                case ConsantHelper.READ_CARD_FAILED:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //错误-12
                case ConsantHelper.READ_CARD_SN_ERR:
                	senriHandleReturnErrorMsg(msg);
                    break;

                //开始交互身份证
                case ConsantHelper.READ_CARD_START:
                	Log.d("BluetoothDevicePlugin", "senrihandleReturnSuccessMsg......开始读卡");
                    break;

            }
        }

    }

    /**
     * 森锐-读取身份证后的处理-成功回调函数
     * @param message
     */
    private void senriHandleReturnSuccessMsg(Message message){
    	Log.d("BluetoothDevicePlugin", "senrihandleReturnSuccessMsg......读取成功");

        // 身份证读取成功，返回所有信息 ,这个类和三元达sdk里的类重名
    	com.sunrise.icardreader.model.IdentityCardZ identityCard = (com.sunrise.icardreader.model.IdentityCardZ) message.obj;

		// 返回结果
		JSONObject resp = new JSONObject();

		try {
				resp.put("respCode", "0000");
				resp.put("respDesc", "读取身份证成功");

				JSONObject data = new JSONObject();
				data.put("name", identityCard.name); // 姓名
				data.put("sexCode", identityCard.sex.equals("男") ? "1" : "0");// 性别 identityCard.sex.equals("男") ? "1" : "0"
				data.put("sexName", identityCard.sex);// 性别
				data.put("birth", identityCard.birth);// 生日yyyymmdd
				data.put("nationCode", "");// 民族编码, 恒鸿达没有
				data.put("nationName", identityCard.ethnicity);// 民族汉字
				data.put("address", identityCard.address);// 住址
				data.put("idNum", identityCard.cardNo);// 身份证号
				data.put("signOffice", identityCard.authority);// 发证机关
				// 有些身份证是永久有效的可能没有结束日期
				String[] usefuldates = identityCard.period.split("-");
				String usefulStartDate = usefuldates[0];
				String usefulEndDate = usefuldates[1];
				if (usefulEndDate == null || usefulEndDate.equals("")) {
					usefulEndDate = "20991231";
				}
				data.put("usefulStartDate", usefulStartDate);// 有效期开始yyyymmdd
				data.put("usefulEndDate", usefulEndDate);// 有效期结束yyyymmdd

				// 处理图片
				Bitmap bitmap = IDImageUtil.dealIDImage(identityCard.avatar);
				String picStr = bitmapToBase64(bitmap); // 照片base64字符串
				data.put("pic", picStr);

				//江苏特供：加密秘钥不为空时对身份证号，姓名，住址 3个字段分别加密，其他省可以不传或者传""，
				if(!TextUtils.isEmpty(this.encryptKey)){
					Log.d("BluetoothDevicePlugin", "encryptKey is ......" + this.encryptKey);
	                String nameEncript = encryptIntface.Id2DataEncry(this.encryptKey, identityCard.name);
	                String idNumEncript = encryptIntface.Id2DataEncry(this.encryptKey, identityCard.cardNo);
	                String addressEncript = encryptIntface.Id2DataEncry(this.encryptKey, identityCard.address);

	                data.put("nameEncript", nameEncript);//姓名加密后
	                data.put("idNumEncript", idNumEncript);//身份证号加密后
	                data.put("addressEncript", addressEncript);//住址加密后
				}

				resp.put("data", data);
		} catch (JSONException e1) {
			Log.d("BluetoothDevicePlugin", "readIDCardSenri......senriHandleReturnSuccessMsg......exception");
			try {
				resp.put("respCode", "0005");
				resp.put("respDesc", "森锐读取身份证异常");
			} catch (JSONException e) {
				e.printStackTrace();
			}

			e1.printStackTrace();
		}

		// 返回结果
		sendRespInfo(resp, normalCallbackContext);
    }

    /**
     * 森锐-读取身份证后的处理-失败回调函数
     * @param message
     */
	private void senriHandleReturnErrorMsg(Message message) {
		// 返回结果
		JSONObject resp = new JSONObject();
		try {
			resp.put("respCode", "0005");
			resp.put("respDesc", "森锐读取身份证异常");
		} catch (JSONException e1) {
			Log.d("BluetoothDevicePlugin",
					"readIDCardSenri......senriHandleReturnErrorMsg......error");
			try {
				resp.put("respCode", "0005");
				resp.put("respDesc", "森锐读取身份证异常");
			} catch (JSONException e) {
				e.printStackTrace();
			}

			e1.printStackTrace();
		}
		// 返回结果
		sendRespInfo(resp, normalCallbackContext);
	}

    /**
     * 卡尔-KT8003 消息处理
     */
    private Handler kaerMsgHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 100) {
//                 proTv.setText(msg.arg1 + " %");
                //proBar.setProgress(msg.arg1);
            } else if (msg.what == 200) {
                //updateResult((IDCardItem) msg.obj);
            } else if (msg.what == 300) {
                //print("读取异常＝" + msg.obj.toString());
            } else if (msg.what == 400) {
                //print(msg.arg1 == 1 ? "服务器已连接" : "服务器已断开");
            } else if (msg.what == 500) {
                //postResult((IDCardItem) msg.obj);
                //print("蓝牙已断开!");
                //btnConnect.setText("连接");
            } else if (msg.what == 600) {
                if (msg.arg1 == 101) {
                    //intensityTv.setText("蓝牙未连接");
                } else if (msg.arg1 != 100 && msg.arg1 != 102) {
                    //intensityTv.setText("信号强度:" + msg.arg1);
                }
            } else if (msg.what == 700) {
                //btnConnect.setEnabled(true);
                if (msg.arg1 == 1) {
                    //intensityFlag = true;
                    //beginCheckIntensity();
                    //btnConnect.setText("断开");
                    //print("蓝牙连接成功!");
//

                } else {
                    //btnConnect.setText("连接");
                    //intensityFlag = false;
                    //print("蓝牙断开!");
                }
            } else if (msg.what == 800) {
                //timeTv.setText(msg.obj.toString());
            } else if (msg.what == 900) {
                //print(getEInfoByCode(msg.arg1));

            }
        }

        ;
    };

	/**
	 * 卡尔-KT8003-工具函数，密码字符串md5加密，登录用
	 * @param source
	 * @return
	 */
	private String getMD5(byte[] source) {
		String s = null;
		char hexDigits[] = { // 用来将字节转换成 16 进制表示的字符
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
				'e', 'f' };
		try {
			java.security.MessageDigest md = java.security.MessageDigest
					.getInstance("MD5");
			md.update(source);
			byte tmp[] = md.digest(); // MD5 的计算结果是一个 128 位的长整数，
			// 用字节表示就是 16 个字节
			char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话，使用两个字符，
			// 所以表示成 16 进制需要 32 个字符
			int k = 0; // 表示转换结果中对应的字符位置
			for (int i = 0; i < 16; i++) { // 从第一个字节开始，对 MD5 的每一个字节
				// 转换成 16 进制字符的转换
				byte byte0 = tmp[i]; // 取第 i 个字节
				str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
				// >>> 为逻辑右移，将符号位一起右移
				str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
			}
			s = new String(str); // 换后的结果转换为字符串

		} catch (Exception e) {
			e.printStackTrace();
		}
		return s;
	}

    //卡尔-KT8003 实现方法 implements OnClientCallback
	@Override
	public void onConnectChange(int arg0) {
		// TODO Auto-generated method stub

	}

	//卡尔-KT8003 实现方法 implements OnClientCallback
	@Override
	public void preExcute(long arg0) {
		// TODO Auto-generated method stub

	}

	//卡尔-KT8003 实现方法 implements OnClientCallback
	@Override
	public void updateProgress(int arg0) {
		// TODO Auto-generated method stub

	}

}
